2018-12-25 15:04:23 +00:00
# [31. Next Permutation](https://leetcode.com/problems/next-permutation/)
# 思路
题意就是实现标准库里的next_permutation函数( 不考虑自定义comp的情况) 。
我们先来看看这个函数,以后可以直接用:
> Transforms the range [first, last) into the next permutation from the set of all permutations that are lexicographically ordered with respect to operator< or comp.
Returns true if such permutation exists, otherwise transforms the range into the first permutation (as if by std::sort(first, last)) and returns false.
`bool next_permutation (first, last)` 返回的是bool型, 如果已经是最后一个排列了则返回false并将数组变成第一个排列(即按照从小到大排好序); 否则返回true并将数组变成下一个排列。
此外还可以传入`comp`参数: `next_permutation (first, last, comp)` 这样就可以自定义数组的大小规则。
下面来分析一下如何实现:
首先应该知道何为下一个排列, 若当前排列组成的数为A, 则下一个排列组成的数B就是刚好比A大( 即没有另外一个排列组成的数C满足A< C < B ) 的排列 。 例如02431的下一个排列是03124 , 03124的下一个排列是03142 。 。 。
可见我们总是贪心地从最低位考虑, 找到第一个不满足从低到高位逐渐增大的数, 例如02431从最低位1到高位不满足逐渐增大的第一个数就是2, 说明2以后的三个数( 431) 已经是这三个数能
2019-01-12 08:39:22 +00:00
组成的最大的数了, 所以下一个排列肯定要把2考虑进去, 而2之前的0就不用考虑了。既然要把2考虑进去, 就说明要用一个数来替换2, 为了使B刚好比A大, 则应该取431中比2大的最小的那个数字即3( 这个过程是一个在有序数组里进行查找的过程, 可以用二分) ,
2018-12-25 15:04:23 +00:00
然后将3和2替换得到3421, 然后再将421 reverse得到3124即可。3124是刚好比2431大的排列。
注意:
* 已经是最后一个排列时,需要单独考虑。
* 交换两个数直接用swap要比手动实现快不少。
时间复杂度O(n), 空间复杂度O(1)
# C++
```C++
class Solution {
public:
void nextPermutation(vector< int > & nums) {
int len = nums.size();
2019-01-12 08:39:22 +00:00
int i = len - 1;
while(i > 0 & & nums[i] < = nums[i - 1]) i--;
2018-12-25 15:04:23 +00:00
if(i == 0) { // 已经是最后一个排列时,需要单独考虑。
reverse(nums.begin(), nums.end());
return;
}
2019-01-12 08:39:22 +00:00
int mid, low = i, high = len - 1;
while(low < = high){ // 二分查找
mid = low + (high - low) / 2;
if(nums[mid] < = nums[i - 1]) high = mid - 1;
else low = mid + 1;
2018-12-25 15:04:23 +00:00
}
2019-01-12 08:39:22 +00:00
// int high = len - 1; // 直接查找
// while(nums[i - 1] >= nums[high]) high--;
swap(nums[high], nums[i-1]); // 用swap击败99%, 若按照下面代码手动实现则击败16%
2018-12-25 15:04:23 +00:00
// int tmp = nums[j];
// nums[j] = nums[i - 1];
// nums[i - 1] = tmp;
reverse(nums.begin() + i, nums.end());
}
};
```