[Leetcode] 31. Next Permutation 解题报告

来源:互联网 发布:mac ps教程 编辑:程序博客网 时间:2024/05/22 10: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, 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    }};


0 0
原创粉丝点击