[leetcode] 31 下一个排列

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 and use only constant 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

这题是 推算下一个排列
比如 {1,2,3} 的排列

1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1

一共6组
很明显 我们发现
第一组 从左到右递增
最后一组从右往左递减
所以 我猜测 排列组 前后顺序的关系 可能是 递增子序列越长越靠前(比如第一组),反之 递减子序列越长越靠后。
如图


image.png

所以 求 下一个排列, 其实就是 希望 把 绿色部分 尽可能的变长。
那么如何以排列的规则使得"绿色部分变长呢"
其实就是使得 粉色部分 最右的 点 以 最慢的速度 增大, 直到被绿色合并。。。
其实这就是 排列干的事情。
所以我的思路是:

  1. 从 右往左 找到 "粉红色"部分的第一个数 , 记为 a
  2. 在 "绿色部分中" 同样从右往左,找到第一个比 a 大的数
  3. swap a,b
  4. 对绿色部分重新排序

当然要处理一下 "粉色"部分为空(最后一组排列), 直接 排序 "绿色部分" 即可。

#include 
using namespace std;
class Solution {
public:
    void nextPermutation(vector& nums) {
        
        //find a 
        int a= -1;
        for(int i = nums.size()-2; i >= 0 ; i--){
            if( nums[i] < nums[i+1]){
                a = i;
                break;
            }
        }
        // 最后一个排列数
        if (a == -1){
            sort(nums.begin() + a +1, nums.end());
            return;
        }
        //find b   
        int b = nums.size()-1;
        while(nums[b] <= nums[a]){
            b--;
        }
        swap(nums[a],nums[b]);
        sort(nums.begin() + a+1, nums.end());
        return;
 
    }
};
image.png

你可能感兴趣的:([leetcode] 31 下一个排列)