这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战
leetcode 下一个排列 实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
示例 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,2,3,4,依次从小到大的排列为:
1,2,3,4
1,2,4,3
1,3,2,4
1,3,4,2
...
4,3,2,1
对于这些排列组合有 第一个列<第二个排列<第三个排列 这种顺序。
要获取这种排列,需要获取下一个比当前排列大的数,并且变大的幅度要最小,那么可以考虑从数组右边往左进行查找, 将左边的一个 [小数] 与右边的一个 [大数] 进行交换,此时得到的排列是变大了的。当然还要控制不能变得太大,所以 [大数] 要尽可能的小, 并且还要将交换后 [大数] 位置右边的元素从小到大排序,这样就可以保证这个排列比之前的大,变大的幅度又是最小的。
具体的例如[1,2,4,3],可以从数组右边往左进行查找,查找到nums[left]<nums[right],第一个左边元素小于右边元素的位置left下的元素, 这时left元素为2,这里的元素2就是 [小数] ;然后在从右往前找到nums[left]<nums[k],第一个大于left位置的元素,此时k下的元素为3,就是 [大数] ,然后就是交换 [小数] 、 [大数] 的位置变成:[1,3,4,2],最后再将 [大数] 右边的元素从小到大升序排列变为:[1,3,2,4],获得最终结果。 同样当第一次从右往左找不到符号条件的元素时,说明当前排列就是最大的排列,直接就可以将整个数组升序排列。
class Solution {
public void nextPermutation(int[] nums) {
int len = nums.length;
int i = len - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
if (i >= 0) {
int k = len - 1;
while (nums[i] >= nums[k]) {
k--;
}
swap(nums, i, k);
}
reverse(nums, i + 1, len - 1);
}
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public void reverse(int[] nums, int i, int j) {
while (i < j) {
swap(nums, i++, j--);
}
}
}