Update 31. Next Permutation.md

This commit is contained in:
唐树森 2019-01-12 16:39:22 +08:00 committed by GitHub
parent a035643521
commit b448596827
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -11,7 +11,7 @@ Returns true if such permutation exists, otherwise transforms the range into the
下面来分析一下如何实现:
首先应该知道何为下一个排列若当前排列组成的数为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
组成的最大的数了所以下一个排列肯定要把2考虑进去而2之前的0就不用考虑了。既然要把2考虑进去就说明要用一个数来替换2为了使B刚好比A大则应该取431中比2大的最小的那个数字即3(这个过程是一个在有序数组里进行查找的过程,可以用二分)
然后将3和2替换得到3421然后再将421 reverse得到3124即可。3124是刚好比2431大的排列。
注意:
* 已经是最后一个排列时,需要单独考虑。
@ -25,18 +25,23 @@ class Solution {
public:
void nextPermutation(vector<int>& nums) {
int len = nums.size();
int i, j;
for(i = len - 1; i > 0; i--){
if(nums[i] > nums[i - 1]) break;
}
int i = len - 1;
while(i > 0 && nums[i] <= nums[i - 1]) i--;
if(i == 0) { // 已经是最后一个排列时,需要单独考虑。
reverse(nums.begin(), nums.end());
return;
}
for(j = len - 1; j >= i; j--){
if(nums[j] > nums[i - 1]) break;
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;
}
swap(nums[j], nums[i-1]); // 用swap击败99%, 若按照下面代码手动实现则击败16%
// 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;