LeetCode 31.Next Permutation

31.Next Permutation

  • 本題主要想介紹 inplace 的交換數據該如何實現。
  • 在c++中,可以通過位操作來實現這一點。
  • 關於位操作,常用的技巧是 一個 0XF 是四個1,這裏需要16個1,所以0XFFFF。前把8作爲高位,後8位作爲低位。因爲一般的運算,8位足夠了。
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,31,3,2
3,2,11,2,3
1,1,51,5,1
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        // 題目比較難懂,其實意圖很簡單,所謂 lexicographically 就是說將各個位上的數看成一個整體
        // 例如. 1,2,3 看成 123。3,2,1 看成 321. 
        // eg. [6 ,5 ,4, 8, 7, 5, 1] => [6,5,5,1,4,7,8]
        // The replacement must be in-place, do not allocate extra memory. !!!

        // 解題思路:
        // 從後向前看,找到第一個不是遞增的數,記爲 p 例如例子中的 p = 4, 其index=2
        // 然後在[p-end] 的區間中,從後向前,找到第一個比 p 大的數,交換他們
        // 然後,對p後面的數,進行升序操作
        // 如果這樣的數 p 不存在,說明,當前序列已經是最後一個了,那麼整體調整序列即可
        if (nums.empty() || nums.size() == 1) return;
        if (nums.size() == 2) {
            int i = 0, j = 1;
            nums[i] &= 0xFFFF;
            nums[i] = nums[i] << 8;
            nums[i] |= nums[j];
            nums[j] = nums[i];
            nums[i] &= 0xFF;
            nums[j] = nums[j] >> 8;
            return;
        }
        int idx = nums.size() - 1;
        // 找第一個不是遞增的
        while (idx > 0 && nums[idx] <= nums[idx-1]) {
            idx--;
        }
        if (idx == 0) {
            int i = 0, j = nums.size() - 1;
            while ( i < j) {
                nums[i] &= 0xFFFF;
                nums[i] = nums[i] << 8;
                nums[i] |= nums[j];
                nums[j] = nums[i];
                nums[i] &= 0xFF;
                nums[j] = nums[j] >> 8;
                i++;
                j--;
            }
        } 
        else {
            // 從後向前,找到第一個比p大的數,交換
            int i = nums.size() - 1;
            int j = idx - 1;
            while (i >= idx) {
                if (nums[i] > nums[j]) {
                    nums[i] &= 0xFFFF;
                    nums[i] = nums[i] << 8;
                    nums[i] |= nums[j];
                    nums[j] = nums[i];
                    nums[i] &= 0xFF;
                    nums[j] = nums[j] >> 8;
                    break;
                }
                i--;
            }
            // 對p後面的數進行升序操作
            for (int i = idx; i < nums.size() - 1; i++) {
                int j = i+1;
                while (j < nums.size()) {
                    if (nums[i] > nums[j]) {
                        nums[i] &= 0xFFFF;
                        nums[i] = nums[i] << 8;
                        nums[i] |= nums[j];
                        nums[j] = nums[i];
                        nums[i] &= 0xFF;
                        nums[j] = nums[j] >> 8;
                    }
                    j++;
                }
            }
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章