题目描述:
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
给你一个整数数组 nums ,找出 nums 的下一个排列。
必须原地修改,只允许使用额外常数空间。
示例:
我刚开始读完题目一脸懵逼。为了防止大家和我一样,我就给大家翻译翻译题目说了啥。
题干的意思是:找出这个数组排序出的所有数中,刚好比当前数大的那个数
比如当前 nums = [1,2,3]。这个数是123,找出1,2,3这3个数字排序可能的所有数,排序后,比123大的那个数 也就是132
如果当前 nums = [3,2,1]。这就是1,2,3所有排序中最大的那个数,那么就返回1,2,3排序后所有数中最小的那个,也就是1,2,3 -> [1,2,3]
按照这个思路,我们继续向下思考,刚好比当前数大的数,那么我们一定是从位数最低的开始去找,即从后面开始找,找的方法也很简单,我以排列[4,5,2,6,3,1]为例,我们先确定第一个位置i,使得i<i+1
i刚开始指向1,i-1指向3,很明显3>1不符合,我们让i–,此时i指向3,i-1指向6,6>3也不符合。
继续让i–,此时的i指向6,i-1指向2<6,符合我们的要求,此时我们找的第一个数2已经确定,我们下面再继续找,找到第二个数,使之与2交换,还是从最低位去找,很明显3刚好符合,我们将2,3交换,最后的结果为:[4,5,3,6,2,1]
最后一步:排序,我们没有动[4,5,2,6,3,1]中2前面的数,所以不用管,只需从2后面排序,使之升序即可。
代码如下:(PS:Java版)
public void nextPermutation(int[] nums) {
int length = nums.length;
if (length <= 1) return;
//倒序查找第一个元素的下标
boolean sig = false;//判断是否找到能够交换的值
int i = length - 1;
for (; i >= 1; i--) {
if (nums[i - 1] < nums[i]) {
sig = true;
break;
}
}
i -= 1;
if (!sig) {//说明未交换
Arrays.sort(nums);
return;
}
//找第二个元素即第一个大于i的元素
int j = length - 1;
for (; j >i; j--) {
if (nums[j] > nums[i]) {
break;
}
}
//交换i,j
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
//重新对i+1之后的元素排序
int[] nu = new int[length - i - 1];
int index = 0;
for (int k = i + 1; k < length; k++) {
nu[index++] = nums[k];
}
Arrays.sort(nu);
index = 0;
for (int k = i + 1; k < length; k++) {
nums[k] = nu[index++];
}
}