题目
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-permutation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码
class Solution {
public void nextPermutation(int[] nums) {
int n= nums.length;
if (nums.length==1) return;
int i=n-2;
for (; i >= 0; i--) {
if (nums[i]<nums[i+1]){//找到下一个排列了,右边全是递减数组(2分)
int bigger=search(nums,nums[i],i+1,n);
swap(nums,bigger,i);//交换索引
//逆序后面的
for (int j = i+1; j < ((i+1)+n)/2; j++) {
swap(nums,j,n-j+i);
}
return;
}
}
if (i==-1) {//已经是最大排列,逆序
for (int j = 0; j < n/2; j++) {
swap(nums,j,n-j-1);
}
}
}
int search(int[] nums,int target,int low,int high){//递减,寻找刚好大于target的值
int midnum;
while (low<high){
int mid=low+(high-low)/2;
midnum=nums[mid];
if (midnum<=target){
high=mid;
}else {
low=mid+1;
}
}
return low-1;
}
void swap(int[] nums,int i, int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}
要点
- 寻找下一个排列,则需要从后往前寻找,找到第一个比后面最大值小的停止,记为i
- 然后用i元素跟后面第一个比其大的数交换
- 最后逆序i+1之后的数组(后面的数组必定是递减的,逆序使得排列最小)
- 如果遍历完都没找到,则说明数组是递减的,返回最小排列,逆序即可
- 第二步的时候,使用二分搜索提高效率