目录
一、题目内容
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
输入 输出
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
原题地址:https://leetcode-cn.com/problems/next-permutation/
二、解题思路
1.理解题意
本体的难点在于对于给出的数字序列,下一个序列是怎么产生的 ?题目给出的示例几乎不需要推导,这也增加了理解的难度。不妨给出多一位的序列来演示看看:
1,2,3,4;
1,2,4,3;
1,3,2,4;
1,3,4,2;
1,4,2,3;
1,4,3,2;
2,1,3,4;
2,1,4,3;
2,3,1,4;
2,3,4,1;
2,4,1,3;
2,4,3,1;
.....
4,3,2,1
四位数字的序列,所有按字典序的序列排列共24中,上面列出一部分。根据上面列出的序列,如果将序列看成数字,可以得出比较直观的等价结论:下一个序列等价于大于当前数字的下一个数字。
2.解题步骤
关键是下一个序列的演变逻辑:
找下一个序列换成找下一个比当前数大的数字会直观很多,比如1,2,4,3的下一个序列是1,3,2,4;
- 步骤1:因为序列是从小到大排列的,所以从后往前找到第一个不为降序的数字a[i];(比如序列1,2,4,3中的2为从后往前第一个不为降序的数)
- 步骤2:从后往前找到在a[i]之后的第一个大于a[i]的数字a[j],并交换这两个数;(比如1,2,4,3中的3为第一个大于2的数)
- 步骤3:把交换之后的位于a[i]之后的数字逆置(使得他们满足升序排列,因为交换之后的数必然满足降序排列,所以只要逆置即可;比如将4,3逆置为3,4便得到了答案需要的写一个序列)
三、代码实现
c++实现:
#include<bits/stdc++.h>
using namespace std;
void nextPermutation(vector<int>& nums) {
int n = nums.size() - 2;
//找到第一个不满足降序的数nums[n]
while (n >= 0 && nums[n] >= nums[n + 1])
n--;
if (n >= 0) {
int i = nums.size() - 1;
//找到nums[n]右边第一个大于
while (i > n && nums[i] <= nums[n])
i--;
//交换nums[n]与nums[i]的值
swap(nums[n], nums[i]);
}
//直接交换后面的降序序列,使得得到的序列是最接近条件序列的下一个序列
reverse(nums.begin() + n + 1, nums.end());
}
int main() {
//标准库中的同功能的函数
// next_permutation(nums.begin(), nums.end());
vector<int> nums = { 4,5,2,6,3,1 };
nextPermutation(nums);
for (int i = 0; i < nums.size(); ++i) {
cout << nums[i] << " ";
}
return 0;
}