题目链接
下一个排列
题目描述
![](https://i-blog.csdnimg.cn/direct/960b03405e524feca9dd608472d7e5a2.png)
![](https://i-blog.csdnimg.cn/direct/02bacb3bf55c4051a2cd5a52f7825e98.png)
注意点
- 必须 原地 修改,只允许使用额外常数空间
- 如果不存在一个字典序更大的排列,则返回字典序最小的排列
- 1 <= nums.length <= 100
- 0 <= nums[i] <= 100
解答思路
- 找到下一个配列的关键是找到比当前字典序更大的字典序,同时要保证字典序的增幅最小(不存在字典序更大的特殊情况除外)
- 怎样找到增幅最小的更大字典序?观察规律可得,要保证字典序更大,需要将数组中前面某个较小的数字与后面某个较大的数字进行交换;要保证增幅更大,则需要从后往前找到第一个nums[i] < nums[i + 1]的数nums[lastMin],再从后往前找到第一个比nums[lastMin]大的数比nums[lastMax]大的数,将两个数进行交换,随后将lastMin左侧的数组变为升序排列即可(此时左侧的数组一定按降序排列)
- 需要特殊考虑的是,如果此时数组已经是最大字典序,则下一个排列是最小字典序,此时数组是降序排列的,只需要将数组改为升序排列即可
代码
class Solution {
public void nextPermutation(int[] nums) {
int n = nums.length;
int lastMin = n - 2;
while (lastMin >= 0 && nums[lastMin] >= nums[lastMin + 1]) {
lastMin--;
}
if (lastMin >= 0) {
int lastMax = n - 1;
while (lastMax > lastMin && nums[lastMax] <= nums[lastMin]) {
lastMax--;
}
swap(nums, lastMin, lastMax);
}
int left = lastMin + 1;
int right = n - 1;
while (left < right) {
swap(nums, left, right);
left++;
right--;
}
}
public void swap(int[] nums, int left, int right) {
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
}
}
关键点