实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
例子:(左侧为输入,右侧为输出结果)
1,2,3->1,3,2
3,2,1->1,2,3
1,1,5->1,5,1
4,2,0,2,3,2,0->4,2,0,3,0,2,2
思路:
从数组尾部往前扫描,检查是否为降序排列,如果是降序排列则继续扫描,直到加入位置i的元素导致尾部不是降序的时候开始调整。调整方法为:找到尾部刚好比i位置数大的数,与之交换,然后把i+1~length位置元素按升序排序即可。
如果扫描完整个数组还没有发生调整,说明数组是降序排列的,把数组排序后输出即可。
我的代码:
public class NextPermutation {
public void nextPermutation(int[] nums) {
int len = nums.length;
for(int i = len-1;i>=0;i--) {
if(!isDec(nums, i)) {
int tmp = nums[i];
//找到合适数交换
for(int j = i+1;j<len;j++)
if(nums[j]<=tmp) {
nums[i] = nums[j-1];
nums[j-1] = tmp;
Arrays.sort(nums, i+1,nums.length);
return;
}
//全部都比tmp大
nums[i] = nums[nums.length-1];
nums[nums.length-1] = tmp;
Arrays.sort(nums, i+1,nums.length);
return;
}
}
//数组已经是最大值了
Arrays.sort(nums);
}
private boolean isDec(int[] nums,int n) {
if(nums.length-1 == n)
return true;
return isDec(nums, n+1)&&nums[n]>=nums[n+1];
}
public static void main(String[] args) {
//测试
int[]nums = new int[] {
2,3,1
};
new NextPermutation().nextPermutation(nums);
for(int i:nums)System.out.print(" "+i);
System.out.println();
int[]nums1 = new int[] {
3,2,1
};
new NextPermutation().nextPermutation(nums1);
for(int i:nums1)System.out.print(" "+i);
System.out.println();
int[]nums2 = new int[] {
4,2,0,2,3,2,0
};
new NextPermutation().nextPermutation(nums2);
for(int i:nums2)System.out.print(" "+i);
System.out.println();
int[]nums3 = new int[] {
1,2,3
};
new NextPermutation().nextPermutation(nums3);
for(int i:nums3)System.out.print(" "+i);
System.out.println();
int[]nums4 = new int[] {
1,3,2
};
new NextPermutation().nextPermutation(nums4);
for(int i:nums4)System.out.print(" "+i);
System.out.println();
}
}
运行结果: