力扣热题100道之31下一个排列

解法

题解中的思路自己写的代码

大体思路跟我的差不多,区别的地方在于题解的实现算法的能力更好一些。比如找到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到最后的数字从小到大排序。

算法流程描述

  1. 寻找转折点

    从右向左遍历数组,定位第一个满足 nums[index] > nums[index-1]的位置 index,该位置标志着字典序增长的潜在转折点。

  2. 处理完全降序情况

    index = 0,表明整个数组呈完全降序排列,此时直接将数组整体按升序排序即可得到最小排列。

  3. 寻找最小交换元素

    index右侧区间内,寻找比 nums[index-1]大的最小元素,记为 minValue(或其位置 minIndex)。

  4. 执行元素交换

    • 情况一 :若右侧不存在比 nums[index-1]更大的元素,则交换 nums[index]nums[index-1]

    • 情况二 :若找到 minValue,则交换 nums[index-1]minValue

  5. 优化剩余序列

    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;
        }
       
    }
}
相关推荐
v_348360876210 小时前
Android native端 堆栈打印
android·算法
residual_fan10 小时前
【学术论文】航空发动机故障诊断智能体:基于持续对比强化学习的动态优化方法
人工智能·算法·数据挖掘·数据分析
GreenTea11 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
深圳满意度咨询12 小时前
医院满意度数字化测评系统:从数据采集到智能决策的技术实践
算法
xiangyun6113 小时前
【408数据结构 08】队列:循环队列判空判满,408年年考,一次讲清
c语言·开发语言·数据结构·c++·算法
xiangyun6113 小时前
【408数据结构 06】双链表、循环链表、静态链表
c语言·开发语言·数据结构·c++·算法
June bug15 小时前
【HCIA- AI(正课)】3.1.人工智能业务流程
职场和发展
302wanger15 小时前
推荐下我的两个AI信息源
算法
索尔~古德曼15 小时前
CF——错题的集合
算法
SL_staff15 小时前
JVS-Logic:从页面配置工具到企业级业务逻辑中枢的技术演进
java·算法·全栈