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++;
                }
            }
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章