力扣31 下一个排列:
提示:trick题,没法做
问题描述
整数数组的一个排列
就是将其所有成员以序列或线性顺序排列。
- 例如
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
的下一个排列。 - 必须
原地
修改,只允许使用额外常数空间。
题解分析:
提示:双指针
从序列后面往前找,在序列某个分隔点一定有一个逆序数列(一个数字也可以看做逆序数列),直到找到逆序数列最前面,即该逆序数列的最大值,找打之后前一个值索引记为i
值,然后从再从后面找一个尽可能小的值比索引i
的值大的值,记为j
,将其交换,因为i+1
一直到nums.length-1
最后的位置都为逆序,将其翻转为正序,即找了下一个排列
解决方案:
借用leetcode题解图
class Solution {
public void nextPermutation(int[] nums) {
//从后往前找到递减终止的数
int i=nums.length-2;
//找到非逆序的第一个数前面的数
while(i>=0&&nums[i+1]<=nums[i]){
i--;
}
if(i>=0){
int j=0;
//找到比nums[i]大的数,尽可能靠右边
for(j=nums.length-1;j>=0;j--){
if(nums[j]>nums[i]){
break;
}
}
swap(nums,i,j);
}
reverse(nums,i+1,nums.length-1);
}
//交换函数
void swap(int[] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
//翻转函数
void reverse(int[] nums,int i,int j){
int l=i,r=j;
while(l<r){
swap(nums,l,r);
l++;r--;
}
}
}