leetcode原题链接:下一个排列
Hot目录:HOT目录
上一篇:HOT98-颜色分类
下一篇:HOT100-寻找重复数
题目描述
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如,arr = [1,2,3]
,以下这些都可以视作 arr
的排列:[1,2,3]
、[1,3,2]
、[3,1,2]
、[2,3,1]
。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
例如,arr = [1,2,3]
的下一个排列是 [1,3,2]
。类似地,arr = [2,3,1]
的下一个排列是 [3,1,2]
。而 arr = [3,2,1]
的下一个排列是 [1,2,3]
,因为 [3,2,1]
不存在一个字典序更大的排列。
给你一个整数数组 nums
,找出 nums
的下一个排列。
必须 原地 修改,只允许使用额外常数空间。
示例 1:
输入:nums = [1,2,3] 输出:[1,3,2]
示例 2:
输入:nums = [3,2,1] 输出:[1,2,3]
示例 3:
输入:nums = [1,1,5] 输出:[1,5,1]
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 100
解题方法:
1. 从右边向左,寻找第一个降序的数字j,对应的波峰为i (j=i-1)。
2. 再从右向左,找到第一个比j大的元素位置k(这个k必然存在,因为nums[j]>nums[i])。
3. 交换nums[j]和nums[k]。
4. 对[j+1, n-1]区间的元素从小到大排序,此时只需要反转下数字即可reverse。
C++代码
#include <iostream>
#include <vector>
#include <algorithm> // std::reverse()
class Solution {
public:
void nextPermutation(std::vector<int>& nums) {
int n = nums.size();
if (n == 0) {
return;
}
// 1.从右边向左,寻找第一个将序的数字j,对应的波峰为i
int i = n - 1; //从右向左寻找第一个波峰的位置
while (i > 0 && nums[i] <= nums[i - 1]) { //比较num[i]和num[i-1]的值,所以这里
i--;
}
if (i == 0) { //i到了最左边,说nums[0]是最大值,此时没有更大的值,则返回最小值(因为数组本身已经是最大值)
std::reverse(nums.begin(), nums.end());
return;
}
int j = i - 1; //j指向第一个波峰左边的位置
// 2.再从右向左,找到第一个比j大的元素位置k(这个k必然存在,因为nums[j]>nums[i])
int k = n - 1;
while (k >= i && nums[k] <= nums[j]) {
k--;
}
// 3. 交换nums[j]和nums[k]
std::swap(nums[j], nums[k]);
// 4. 对[j+1, n-1]区间的元素从小到大排序,此时只需要反转下数字即可reverse
std::reverse(nums.begin() + j + 1, nums.end());
}
};