leetcode 31 Next Permutation

题意

找到下一个permutation是什么,对于一个数组[1,2,3],下一个排列就是[1, 3, 2]

链接

https://leetcode.com/problems/next-permutation/

思考

首先任何一个permutation满足一个性质,从某个位置往后一定是降序
比如[2,1,4,3]这么一个排列,3和4之间是没有办法交换的了,因为此时已经达到了[2,1]开头的最大值,只能改变1才能够变成一个更大排列。

解法

所以步骤分为三步:
记n为num.size();

  1. 从右往左找,找到位置i,使得nums[i-1] < nums[i]
  2. 此时nums[i-1]是我需要交换的其中元素,我需要在下标区间[i, nums.size()-1]中找到最后一个大于nums[i-1]的元素,和nums[i-1]交换
  3. 把[i,n]这个区间的元素升序排列

解法

//最终优化版本
int i = nums.size() - 1;
while( i > 0 && nums[i-1] >= nums[i]) i--;
if (i == 0) {
    reverse(nums.begin(), nums.end());
    return;
}
int l = i;
int r = nums.size() - 1;
int t = nums[i-1];
//二分找到最后一个严格大于nums[i-1]的值
while(l < r) {
    int mid = l + (r - l)+1 / 2;
    if(nums[mid] > t) {
        l = mid;
    } else {
        r = mid - 1;
    }
}
//这里不需要判断答案是否存在,因为while( i > 0 && nums[i-1] >= nums[i]) i--;已经保证了二分一定有值,至少有一个元素是比nums[i-1]要大


//交换两个数
swap(nums[i-1], nums[l]);
//把从第i位开始的数字到末尾升序排列
reverse(nums.begin()+i, nums.end());

算法复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

//没有用二分的版本
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int i = nums.size()-2;
        for(; i >= 0; i--) {
            if(nums[i] < nums[i+1])
                break;
        }
        if (i == -1) {
            return reverse(nums.begin(),nums.end());
        }
        
        int j = nums.size()-1;
        for(; j >= 0; j--) {
            if(nums[j] > nums[i]) {
                swap(nums[j], nums[i]);
                break;
            }
        }
        return reverse(nums.begin()+i+1, nums.end());
    }
};

算法复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值