[Leetcode] 31. Next Permutation 解题报告

题目

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,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

思路

        据说Next Permutation也是一道高频题目。这里直接上最优解法的思路(据说STL中的next_permutation也就是这么实现的):

1)从右到左找到数组中的第一个顺序对(即满足nums[i-1] < nums[i]的最大的i值)。如果没有找到,说明数组是完全严格递减的,此时直接翻转数组,并返回。

2)从nums[i]开始从左到右,找到大于nums[i-1]的最小的数,并交换nums[i-1]和该数的值。由于从nums[i]到末尾的所有数字都是严格递减的,所以其实只要找到第一个小于等于nums[i-1]的值,就可以知道它的前一个数字即为大于nums[i-1]的最小的数。

3)翻转从nums[i]到末尾的所有数字(思考一下为什么这里只需要翻转,而不需要排序?)。

        仔细想一想,其实步骤2)还可以优化:由于从nums[i]到末尾的所有数字都是严格递减的,所以在查找最后一个大于nums[i-1]的值的时候可以采用二分查找,将时间复杂度从线性级别降低到对数级别(不过对于大多数比较短的数组而言,可能优化效果不是很大)。在下面的代码中为了简便,我们直接用线性扫描的方法了。我想如果在面试的时候,你在最后能告诉面试官其实你还可以优化这一部分,估计会有加分。

代码

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        int len = nums.size(), i = len - 1;
        if(len == 0)
            return;
        while(i > 0 && nums[i-1] >= nums[i])            // try to find the first increasing pair
            i--;
        if(i == 0)                                      // not found, so reverse the whole array
        {
            reverse(nums.begin(), nums.end());
            return;
        }
        int right = i;
        while(right < len && nums[right] > nums[i - 1]) // find the last element that is larger than nums[i-1]
            right++;
        swap(nums[i-1], nums[right - 1]);
        reverse(nums.begin() + i, nums.end());          // we do not need to sort, just reverse
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值