问题描述
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place and use only constant extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
题目要求: 输入一个整型数组,输出按照数值大小为顺序的下一个排列
解题思路
这题拿到手需要先分析一下,如何找到大小排序的下一个排列? 可以按照数字的大小来比较,最后一位是个位,倒数第二位是十位,然后是百位,千位……然后只需要将其中的几位数字换一下位置即可。首先从后往前找,找到第一个开始变小的数字,这个时候只需要把这个变小后的数字,跟它后面一位比它大一些的数字调换即可。例如132719643210这个数字,从最后一位0开始往后找,找到第一个开始下降的数字1,把1跟后面比它大的一个数字换即可,因为需要的是next permutation,所以找到的值不能太大,只能找到刚好比它大的数字2,所以换成了132729643110,这时候实现了增大.因为这里后面的数字都是按照顺序递减的,所以按顺序一个一个找即可。但是可以看到最后几位是9643110,很显然不是当前前面位数13272开头能组成的最小数字,所以后面的数字直接排序一下即可。由于这里的数字也都是倒序排列的,所以直接颠倒一下位置即可。132719643210 → 132729643110 → 132720113469
代码实现
//当时写的时候没考虑到后面是有序的数组,所以用了Arrays.sort()所以时间复杂度应该会稍微高一些
public void nextPermutation(int[] nums) {
if(nums.length == 0) return;
reverseArray(nums, nums.length);
for(int i = 0; i < nums.length-1; i++) {
if(nums[i] > nums[i+1]) {
for(int j = 0; j<=i; j++) {
if(nums[j]>nums[i+1]) {
int temp = nums[j];
nums[j] = nums[i+1];
nums[i+1] = temp;
break;
}
}
Arrays.sort(nums,0,i+1);
reverseArray(nums, i+1);
reverseArray(nums, nums.length);
return;
}
}
Arrays.sort(nums);
}
public void reverseArray(int[] nums, int end) {
for(int head = 0, tail = end-1-head; head<=tail; head++, tail--) {
int temp = nums[head];
nums[head] = nums[tail];
nums[tail] = temp;
}
}
复杂度分析:
时间复杂度:O(nlogn) (如果没用sort而是直接颠倒的话时间复杂度就是O(n))
空间复杂度:O(1)