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,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
解答:
题目看似不难,其实还是很有门道的,需要求“下一个排列”,如何定义下一个,这个问题有些像“数字大小的排序问题”,假设给定1、2、3三个数字,从小到大来做排列,那显然结果是123,132,213,231,312,321。现在的问题在于,如何厘清算法的流程,假设数组长度为n,数组名为nums,步骤如下:
- 从后往前遍历,找到index为i的数字,满足nums[i] < nums[i-1],若没有则序列为完全逆序,翻转整个序列
- 从后往前,遍历[i+1,n-1],找到最大的j满足nums[j] > nums[i]
- 交换nums[j]和nums[i]
- 将nums[i+1]~nums[n-1]的所有数字翻转
至于为何要这么做,我的理解是因为“下一个”,所以要吃透含义,有点类似于数字进位的问题,首先找到一个峰值,接下来寻找比当前的数字大但最接近当前数字的数,所以就有了上面的算法,代码如下:
class Solution { public: void nextPermutation(vector<int>& nums) { int len = nums.size(),i,j; for (i = len - 2; i >=0; i--) if (nums[i] < nums[i + 1]) break; if (i < 0) reverse(nums.begin(), nums.end()); else { for (j = len - 1; j > i; j--) if (nums[j] > nums[i]) break; swap(nums[j], nums[i]); reverse(nums.begin() + i + 1, nums.end()); } } };
时间复杂度:O(N)
空间复杂度:O(1)
参考链接:
https://www.cnblogs.com/eudiwffe/p/6260699.html
https://leetcode.com/problems/next-permutation/discuss/13867/C%2B%2B-from-Wikipedia