先举个例子吧
12452568691531,我们要找这个数的下一个排列,相当于找1531的下一个排列,然后拼接前面的若干个数。
算法如下:
我们先从后往前找,找到一个数比它前一个数要大
1245256869 1531
我们将最后这个1531分开来,现在我们要做的就是将1和后面这个531中,比1稍微大一点点的数,进行交换,然后把交换后的后面几个数,进行排序。
为什么那么做呢,我们观察样例,就可以发现,实际上发生改变的,是原数组中,是一个终点为末尾的最长递减序列【实际上也可能只有一个数】以及这个序列前一个数。我们现在要更新这个序列,所以我们还需要这个序列前一个数【也就是那个比这个序列头小的一个数,当然也可能不存在,那就代表数组本身就是一个逆序数组,我们只需要直接对数组进行排序或者反转】,这相当于后面那个逆序序列的最高位,我们现在要找下一个排列,也就是要让这个数变大。与这个数交换的应该是后面那个逆序序列中,比这个数刚好大一点的数,也就是所有比这个数大的数中最小的那个。交换完后,因为最高位变大了,后面的剩余位应该更小,所以进行排序即可。
class Solution {
public void nextPermutation(int[] nums) {
int len = nums.length;
int index = -1;
for (int i = len - 1; i > 0; i--) {
if (nums[i] > nums[i - 1]) {
index = i;
break;
}
}
if (index == -1) {
Arrays.sort(nums);
return;
}
// 二分查找一个比nums[index-1]大的数
int l = index;
int r = len - 1;
int change = index;
while (l <= r) {
int mid = (l + r) >> 1;
if (nums[mid] <= nums[index - 1]) {
r = mid - 1;
continue;
} else if (mid == len - 1 || nums[mid + 1] <= nums[index - 1]) {
change = mid;
break;
}
l = mid + 1;
}
nums[index - 1] += nums[change];
nums[change] = nums[index - 1] - nums[change];
nums[index - 1] -= nums[change];
Arrays.sort(nums, index, len);
return;
}
}