31.下一个排列
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
PS:刚看题目一脸懵逼~~。我的理解:给定一个数组,把这个数组想成一个数字,返回一个最小的且比这个数字大的数
如 给定 [4,3,2,6,5,1],需要返回 [4,3,5,1,2,6]
解题思路:
明白题意以后,解题就相对容易了~
- 从右往左遍历,找到第一个较小数。如 [4,3,2,6,5,1],遍历到「2」时,「2」比「6」小,「2」即为第一个较小数。
- 「2」以后的数字一定为降序(包含相等),再接着从右往左遍历找出第一个比「2」大的数字即「5」,交换「2」和「5」的位置。序列变为 [4,3,5,6,2,1]
- 交换以后,当前「5」位置以后的序列肯定也是降序(包含相等),反转「5」以后的序列即得到最小的较大数。
方法一:
public void nextPermutation(int[] nums) {
int i = nums.length - 2;
// 从右往左寻找第一个较小数
while (i >=0 && nums[i] >= nums[i + 1]) {
i--;
}
// 此时 i 之后的数为降序(包括相等),从右往左寻找第一个比 i 大的数并交换
if (i >= 0) {
int j = nums.length - 1;
while (j >= 0 && nums[j] <= nums[i]) {
j--;
}
swap(nums, i, j);
}
// 交换以后, 原 i 以后的数依然为降序(包括相等),将后面的数字反转即为最小的较大数
// 如果 i = -1,说明原数组为降序,此时反转数组将数组变为升序与题目要求对应
int left = i + 1;
int right = nums.length - 1;
while (left < right) {
swap(nums, left++, right--);
}
}
public void swap(int[] nums, int i ,int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}