- 原题链接:31. 下一个排列
思路
- ① 从右边找出一个尽可能大的数,和左边的数进行交换 ——> 交换后得到的数 就是 字典序更高
- ② 字典序高,但不代表其就是下一个 ——> 如何找下一个?
- 左边的小数,尽可能靠右
- 右边的大数,尽可能的小(比左边的小数大一点点)
目标
- ① 找到数组的拐点 ——> 从右向左遍历 ——> nums[i] < nums[i+1] 则找到了拐点 i+1
- ② 找到拐点右侧第一个 nums[i] 大的元素,此时记录 为 j ——> 从右向左遍历
- ③ 将元素 i 和 元素 j 交换,之后
sort(i+1,len-1)
- ④ 如果不存在拐点,此时直接 reverse 整个数组
2- 实现
⭐31. 下一个排列——题解思路
class Solution {
public void nextPermutation(int[] nums) {
// 1. 先找拐点前的i
int i = 0 ;
int len = nums.length;
for(i = len-2 ; i >= 0;i--){
if(nums[i] < nums[i+1]) break;
}
// 不存在 直接 reverse
if(i == -1){
int L = 0;
int R = len-1;
while(L<R){
swap(nums,L++,R--);
}
return;
}
// 找到第一个 略大
int j = len-1;
for( ; j > i ;j--){
if(nums[j] > nums[i]) break;
}
// 交换 i 和 j
swap(nums,i,j);
// reverse [i+1,len-1];
int L = i+1;
int R = len-1;
while(L<R){
swap(nums,L++,R--);
}
}
private void swap(int[] nums,int i,int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
3- ACM 实现
public class nextP {
public static void nextP(int[] nums){
//1. 先找拐点前一个 i
int i = 0;
int len = nums.length;
for(i = len-2 ; i >=0 ;i++){
if(nums[i] < nums[i+1]) break;
}
// 如果 i == -1 直接 reverse
if(i==-1){
int L = 0;
int R = len-1;
while(L<R){
swap(nums,L++,R--);
}
return;
}
// 找到 j
int j =len-1;
for(; j>i;j--){
if(nums[j] > nums[i]) break;
}
// 交换 i 和 j
swap(nums,i,j);
// 3. 翻转 [i+1,len-1]
int L = i+1;
int R = len-1;
while (L < R){
swap(nums,L++,R--);
}
}
private static void swap(int[] nums,int i ,int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
input = input.replace("[","").replace("]","");
String[] parts = input.split(",");
int[] nums = new int[parts.length];
for(int i= 0 ; i < nums.length;i++){
nums[i] = Integer.parseInt(parts[i]);
}
nextP(nums);
System.out.println("结果是");
for(int i : nums){
System.out.print(i+" ");
}
}
}