LeetCode/solutions/31. Next Permutation.md
2019-01-12 16:39:22 +08:00

53 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [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的下一个排列是0312403124的下一个排列是03142。。。
可见我们总是贪心地从最低位考虑找到第一个不满足从低到高位逐渐增大的数例如02431从最低位1到高位不满足逐渐增大的第一个数就是2说明2以后的三个数431已经是这三个数能
组成的最大的数了所以下一个排列肯定要把2考虑进去而2之前的0就不用考虑了既然要把2考虑进去就说明要用一个数来替换2为了使B刚好比A大则应该取431中比2大的最小的那个数字即3这个过程是一个在有序数组里进行查找的过程可以用二分
然后将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();
int i = len - 1;
while(i > 0 && nums[i] <= nums[i - 1]) i--;
if(i == 0) { // 已经是最后一个排列时,需要单独考虑。
reverse(nums.begin(), nums.end());
return;
}
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;
}
// int high = len - 1; // 直接查找
// while(nums[i - 1] >= nums[high]) high--;
swap(nums[high], nums[i-1]); // 用swap击败99%, 若按照下面代码手动实现则击败16%
// int tmp = nums[j];
// nums[j] = nums[i - 1];
// nums[i - 1] = tmp;
reverse(nums.begin() + i, nums.end());
}
};
```