

解法
题解中的思路自己写的代码
大体思路跟我的差不多,区别的地方在于题解的实现算法的能力更好一些。比如找到index右边的最小的大数。可以直接从右边向左边遍历,而我的做法是从左边向右边遍历,这就导致做法非常的麻烦,要判断的东西很多。

class Solution {
public void nextPermutation(int[] nums) {
int n=nums.length;
int index=n-1;
while(index>0&&nums[index]<=nums[index-1]){
index--;
}
if(index==0){
sort(nums,0);
}else{
for(int j=n-1;j>=index;j--){
if(nums[j]>nums[index-1]){
swap(nums,index-1,j);
sort(nums,index);
break;
}
}
}
}
public void sort(int []nums,int i){
for(int k=i;k<nums.length;k++){
int min=k;
for(int s=k;s<nums.length;s++){
if(nums[min]>nums[s])min=s;
}
swap(nums,min,k);
}
}
public void swap(int []nums,int i,int j){
int tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
}
自己的解法
思路
从右向左遍历数组,找到第一个数字记作index,这个数字比前一位数字要大,然后判断
如果index=0,也就是数组是递减的,那么直接将整个数组从小到大排个序就好了。
在index向右遍历,找到index右边的比index-1大的最小的数字记作min,判断
如果右边没有比index更大的数字那么交换index和index-1,将从index到最后的数字从小到大排序
如果找到了min,交换index-1和min,将index到最后的数字从小到大排序。
算法流程描述
-
寻找转折点
从右向左遍历数组,定位第一个满足
nums[index] > nums[index-1]的位置index,该位置标志着字典序增长的潜在转折点。 -
处理完全降序情况
若
index = 0,表明整个数组呈完全降序排列,此时直接将数组整体按升序排序即可得到最小排列。 -
寻找最小交换元素
在
index右侧区间内,寻找比nums[index-1]大的最小元素,记为minValue(或其位置minIndex)。 -
执行元素交换
-
情况一 :若右侧不存在比
nums[index-1]更大的元素,则交换nums[index]与nums[index-1]。 -
情况二 :若找到
minValue,则交换nums[index-1]与minValue。
-
-
优化剩余序列
将
index至数组末尾的子序列按升序排序,确保该区间构成最小字典序,从而得到严格的下一个排列。
这道题目中学到的
在这道题目中我很迷糊,在如何找到index右边的比index-1大的最小的数字上花了很长时间。最后我发现,直接在主方法的外面单独创建一个方法来专门解决这个问题,会好很多。

class Solution {
public void nextPermutation(int[] nums) {
int n=nums.length;
int index=n-1;
int poi=n-1;
while(index>0&&nums[index]<=nums[index-1]){
if(index!=n-1)poi--;
index--;
}
if(index==0){
sort(nums,0,n-1);
}else{
int mini=findMin(nums,index+1,nums[index-1]);
if(mini==-1){
swap(nums,index,index-1);
sort(nums,index,n-1);
}else{
swap(nums,mini,index-1);
sort(nums,index,n-1);
}
}
}
public void sort(int []nums,int i,int j){
for(int k=i;k<=j;k++){
int min=k;
for(int s=k;s<=j;s++){
if(nums[min]>nums[s])min=s;
}
swap(nums,min,k);
}
}
public void swap(int []nums,int i,int j){
int tmp=nums[i];
nums[i]=nums[j];
nums[j]=tmp;
}
public int findMin(int []nums,int i,int num){
int mini=i;
int n=nums.length;
if(i>n-1)return -1;
for(int k=i;k<nums.length;k++){
if(nums[k]<=num){
mini=k;
break;
}
}
if(mini==i&&nums[mini]<=num){
return -1;
}else if(mini==i&&nums[mini]>num){
return n-1;
}else{
return mini-1;
}
}
}