「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
题目:给定一个数组,将数组中元素顺序排列组成一个数字,将这些数字重新排列,得到下一个比当前数大的数字(要求所有数字全排列之后从小到大排序,当前数字的下一个数字),如果不存在比当前数字大的数字,则返回全排列最小的那个数字。要求,在原数组上进行更改。
解题思路
一开始的简单思路,得到所有元素的全排列,将这些数字从小到大排序,遍历序列,找到与当前元素相同的元素,返回其下一个序列,转为数组。这样思路可行,但题目要求在原数组上进行更改,很明显这种思路是不符合的。参考题解之后:
要得到所要求的数字,那么必须将数组后面的大数字和前面的小数字进行交换,并且交换之后还得保证原小数字之和的元素保持有序。
步骤如下:
- 首先数组元素从后往前遍历,找到符合
a[i-1]<a[i]的这个序列,保存索引i-1,其为上述前面的小数字。 - 判断索引
i-1,如果为0且满足a[0]>a[1],则代表当前数组严格降序,将数组重排结束即可。否则i-length-1必然是严格降序,此时将数组从后往前遍历,找到第一个元素符合a[j]>a[i-1]的,交换彼此。 - 将数组
i-length-1的元素进行排序,nums即为最终结果。
代码如下:
public static void nextPermutation(int[] nums) {
int len = nums.length;
if(len<=1) return;
int index = len-1;
for(;index>0;index--){
if(nums[index-1]<nums[index]){
index--;
break;
}
}
if(index==0&&nums[0]>nums[1]){
Arrays.sort(nums);
return;
}
for(int i=len-1;i>index;i--){
if(nums[i]>nums[index]){
swap(nums, index, i);
break;
}
}
reverse(nums, index+1, len-1);
}
public static void swap(int[] nums, int a, int b){
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
public static void reverse(int[] nums, int start, int end){
while(start<end){
swap(nums, start++, end--);
}
}
时间复杂度为,空间复杂度为。看了一下官方的,思路一致更加简练,但上述代码逻辑清晰,比较友好。