【中等】31-下一个排列 Next Permutation

题目

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,31,3,2
3,2,11,2,3
1,1,51,5,1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-permutation

解法

解题思路

如果没有下一个排列,那么一定是从大到小的有序序列,如果有下一个排列,那么一定可以将序列分成两部分:无序的前缀和有序的最大后缀,如对于9,4,7,6,5,3,2来说,从后向前,2,3,5,6,7是有序后缀,9,4是前缀,那么下一个要排列一定是把前缀的最后一位4换成后缀中比4大且最接近的5,且新后缀是从小到大排序的,可以使用一个序列把后缀23567存起来,找到5之后再把23467放回原来后缀的位置,5放到原来的4的位置(官方方法交换45之后翻转)

代码

代码一:queue
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int size = nums.size(), change = 0, changenum = 0;
        if(size <= 1) return;
        queue<int> ord;
        for(change = size-1; change > 0; --change){
            ord.push(nums[change]);
            if(nums[change-1] < nums[change]){
                change = change-1;
                changenum = nums[change];
                break;
            }
        }
        cout << change << changenum << endl;
        if(change == 0 && nums[0] >= nums[1]){
            int currpos = 0;
            nums[size-1] = nums[0];
            while(!ord.empty()){
                nums[currpos++] = ord.front();
                ord.pop();
            } 
            return;
        } 
        bool find = false;
        int currpos = change+1;
        while(!ord.empty()){
            int newnum = ord.front();
            if(newnum > changenum && !find){
                find = true;
                nums[currpos++] = changenum;
                nums[change] = newnum;
            }
            else nums[currpos++] = newnum;
            ord.pop();
        }
    }
};
代码二:交换
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int size = nums.size(), change = -1, changenum = 0;
        if(size <= 1) return;
        queue<int> ord;
        for(int i = size-2; i >=0; --i){
            if(nums[i]<nums[i+1]){
                change = i;
                break;
            } 
        }
        if(change != -1){
            for(int i = change+1; i < size; ++i){
                if(nums[i] <= nums[change]){
                    swap(nums[i-1], nums[change]);
                    break;
                }
                else if(i == size-1){
                    swap(nums[i], nums[change]);
                    break;
                }
            }
        }
       int l = change+1, r = size-1;
       while(l < r){
           swap(nums[l], nums[r]);
           l++;
           r--;
       }
    }
};
posted @ 2020-04-27 19:15  陌良  阅读(121)  评论(0编辑  收藏  举报