每周LeetCode算法题(三):Next Permutation

来源:互联网 发布:赌博游戏源码 编辑:程序博客网 时间:2024/06/05 20:27

每周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

解法分析

题目意思是要求把一个数组从低下标到高下标看成一个从高位到低位的整数,然后返回用各位上的数字重新组合成的一个刚好大于原数的整数,若已为最大可表示的数则返回最小可表示的数。

这道题解题的关键是要知道一个规律。那就是原数和所求数的前m位都相等(0<=m<=n-2, n为总位数),而原数第m+1位到末位上的数必定呈降序。那么所求的数为了恰好大于原数,只能从第m位后找恰大于第m位的数来和第m位上的数交换位置(第m位上的数一定这样能确保影响只到达第m位,不会影响到第m位之前,即不会求得过大的数)。交换后已经能确保数字增大了,但过分增大了,因为原来第m位后的数字已是降序排列(例如4321,肯定是末几位最大的排列),这时需要将这一段反向(1234,肯定是末几位最小的排列)。

所以理一下思路,从后往前找,找到第一个不满足降序的数位,用一个变量st来保存这个数(设为x)的下标(即之后交换的位点)。第二步再从这开始往后找,找到一个恰大于x的数的下标en(nums[en] > x >= nums[en - 1])。第三步交换nums[st]和nums[en]。最后反转下标st + 1到末位上的所有位。

关于复杂度,往前找是O(n),往后找也是O(n),交换是O(1),反转是O(n)。所以别看挺长,最后还是O(n)。

剩下的工夫就是代码了,当然,还是要注意一些边界上的问题,例如数组长度是否为零啦这些.

C++代码展示

class Solution {public:    void nextPermutation(vector<int>& nums) {        if (nums.size() == 0) {            return;        }        int st = nums.size() - 1, en = nums.size() - 1;        for (int i = nums.size() - 1; i >= 0; i--) {            if (i != 0) {                if (nums[i - 1] >= nums[i]) {                    st = i - 1;                } else {                    st = i - 1;                    break;                }            } else {                st = i - 1;            }        }        for (int i = st + 1; i < nums.size(); i++) {            if (nums[i] > nums[st]) {                if (i != nums.size() - 1) {                    if (nums[i + 1] <= nums[st]) {                        en = i;                        break;                    }                } else {                    en = i;                }            }        }        if (st != -1) {            int tmp = nums[st];            nums[st] = nums[en];            nums[en] = tmp;        }        st++;        for (int i = st, j = nums.size() - 1; i < j;) {            int tmp = nums[i];            nums[i] = nums[j];            nums[j] = tmp;            i++;            j--;        }    }};
阅读全文
1 0