实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
我的解法:要将给定数字序列重新排列成字典序中下一个更大的排列,目的是找一个比当前数字大且尽可能小的数,只需将数字序列后面的大数与前面的小数交换。首先从右往左查找打破升序规律的下标i,从左往右看[i+1, len)为降序序列;然后在[i+1,len)中找到比nums[i]大的最小数nums[j],并交换nums[j]和nums[i],交换后[i+1, len)仍为降序序列,最后一步是将[i+1, len)翻转成升序序列,即可得到比当前数字大且尽可能小的数。
时间复杂度:O(n),空间复杂度:O(1)
class Solution {
public void nextPermutation(int[] nums) {
int len = nums.length, i, j, temp;
/*从右往左查找打破升序的点i, [i+1,len)为降序序列*/
for (i = len - 2; i >= 0; i--) {
if (nums[i] < nums[i+1]) break;
}
/*若点i为-1, 说明整个序列是降序序列, 直接翻转*/
if (i == -1) {
Arrays.sort(nums);
return;
}
/*查找[i+1, len)比nums[i]大的最小元素*/
for (j = len - 1; j > i; j--) {
/*找到比nums[i]大的最小元素后交换*/
if (nums[j] > nums[i]) {
temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
break;
}
}
/*交换后[i+1,len)仍为降序序列, 翻转[i+1,len)使其变成升序*/
Arrays.sort(nums, i+1, len);
}
}