31. 下一个排列
下一个排列,可以说是下一个更大的数。
怎么找下一个更大的数呢,实际上就是找最后一个存在逆序的元素i,此时把之前和之后分成两片,需要找打之后那一片里面第一个大于i的数字和i交换,然后将下一片升序排序。
如何获得呢?其实就是从后往前找,找到第一个i使得nums[i]<nums[i+1]。此时我们知道,i之后的那一片一定是降序的。
于是我们可以用二分查找,加上替换,以及倒转下一片来求解。
但需要注意的是,java里面的Arrays.binarySearch查找是只能查找升序的,所以我们可以先倒转下一片成升序,然后再使用类库。
或者是我们直接写一个类库求降序的数组。
public void nextPermutation(int[] nums) {
int i = nums.length - 2;
for (; i >= 0; i--) {
if (nums[i] < nums[i + 1]) break;
}
if (i == -1) {
trans(nums, 0, nums.length - 1);
return;
}
int t = binarySearch1(nums, i + 1, nums.length, nums[i]);
//也可以使用Arrays. binarySearch(nums, i + 1, nums.length, nums[i]),但得先
// swap(nums, i, t);
if (t < 0) t = -t - 1;
else {
while (nums[t] == nums[i]) t--;
}
swap(nums, i, t);
trans(nums, i + 1, nums.length - 1);
}
//这样写,如果找不到,一定左右互易
public int binarySearch1(int[] nums, int low, int high, int target) {
high = high - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
if (nums[mid] < target) high = mid - 1;
else if (nums[mid] == target) return mid;
else low = mid + 1;
}
return -(high + 1);
}
public void swap(int[] nums, int s0, int s1) {
int temp = nums[s0];
nums[s0] = nums[s1];
nums[s1] = temp;
}
public void trans(int[] nums, int from, int to) {
while (from < to) {
swap(nums, from++, to--);
}
}