题意为,如果将一个数组从小到大全排列,然后给出其中任意一个全排列的情况,然让你给出这种情况在全排列中的下一个情况。
例如,给你 [ 1 , 3, 2 ] ,希望你返回 [2, 3, 1]
数组的数据量在 1 <= nums.length <= 100
如果真的要把全排列算出来,然后再二分,简单计算一下 P100 就知道大概数据容量规模应该超上限了。
所以解题思路是找到某一种规律,然后做位置交换。
如果我们称一个数组,里面所有的数据都满足从小到大为正序。反之,则可以称逆序。那么正序所代表的数字一定是小于逆序所代表的数字的。
所以当我们要找到一个全排列情况的下一种,那么就是要找到在全排列中比他大,但没有比这个数更大的一个数。可以从右向左找到最大的逆序子数组,答案只和这个子数组和他前面那个数字有关,只需要把这些数字重新组合就能找到答案。
可以先找几个例子,可以发现只需要把这个子数组前面那个数字和子数组找出一个最小且比他大的数组做交换,然后将交换位置过后的子数组排序,就是答案了。
public void nextPermutation(int[] nums) {
boolean change = false;
for(int i = nums.length - 1;i>=0;i--) {
if(i < 1) continue;
// 找最大逆序数组
if(nums[i] > nums[i-1]) {
int index = i;
int val = nums[index];
// 找最小且比nums[i-1]大的数字
for(int j = i; j < nums.length; j++) {
if(nums[j] > nums[i-1] && nums[j] < val) {
index = j;
val = nums[j];
}
}
int tmp = nums[i-1];
nums[i-1] = nums[index];
nums[index] = tmp;
//将逆序数组重新排序构造最小的正序
Arrays.sort(nums, i, nums.length);
change = true;
}
if(change) break;
}
// 数组本身是逆序的 将正序数组输出
if(!change) {
for(int i = nums.length - 1; i >=nums.length/2 ; i--) {
int tmp = nums[i];
nums[i] = nums[nums.length - i - 1];
nums[nums.length - i - 1] = tmp;
}
}
}