原题目描述
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
题目大意
该题目给定一串数字,要求求出该数字串的下一置换,直接在原参数vector上进行操作,无需返回值.题意还是很好理解的,只要知道了什么是置换,了解置换的规则还是很好AC的。
解题思路
这里,我通过几个例子来说明如何求出下一置换:
例子:【2,1,3,8,6,5,4】
第一步,我们从数组末尾开始向前找,找出第一个非递增的数(这里的递增是从后往前算的),即 nums[i] < nums[i+1],这个例子我们可以找出这个数为3,我们记为num1;
(特殊情况:如果找不到这样一个数,说明该数组是完全按递减排序的,此时我们只需要对其做个reverse便得到下一置换了)
第二步,如果第一步找到了num1,我们再次从数组末尾开始向前找,找到第一个比num1大的数(此处是一定能够找到了,因为第一步一经确定num1是第一个非递增的数),这个例子我们可以找到这个数为4,我们记为num2;
第三步,交换num1和num2,并将num2和num1(包括num1但不包括num2)之间的数按照升序排序,便得到下一置换,此处交换num1和num2得到【2,1,4,8,6,5,3】,将num2和num1(包括num1但不包括num2)之间的数排序,得到【2,1,4,3,5,6,8】,这便是结果。
C++实现代码
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int len = nums.size(), k = 1;
if (len <= 1)
return;
if (len == 2) {
swap(nums[0], nums[1]);
return;
}
for (int i = len-1; i >= 1; i--) {
// 第一步,从末尾找出第一个非递增的数nums[i]
if (nums[i] > nums[i-1]) {
for (int j = len-1; j >= i; j--) {
// 第二步,从末尾找出找出第一个比nums[i]大的数nums[j]
if (nums[j] > nums[i-1]) {
// 交换并排序
swap(nums[j], nums[i-1]);
sort(nums.begin() + i, nums.end());
return;
}
}
}
}
// 如果未找到第一个递增的数,则翻转得到下一置换
reverse(nums.begin(), nums.end());
}
};