力扣热题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;
        }
       
    }
}
相关推荐
LYFlied43 分钟前
【每日算法】LeetCode 153. 寻找旋转排序数组中的最小值
数据结构·算法·leetcode·面试·职场和发展
唐装鼠1 小时前
rust自动调用Deref(deepseek)
开发语言·算法·rust
ytttr8732 小时前
MATLAB基于LDA的人脸识别算法实现(ORL数据库)
数据库·算法·matlab
jianfeng_zhu3 小时前
整数数组匹配
数据结构·c++·算法
smj2302_796826523 小时前
解决leetcode第3782题交替删除操作后最后剩下的整数
python·算法·leetcode
LYFlied4 小时前
【每日算法】LeetCode 136. 只出现一次的数字
前端·算法·leetcode·面试·职场和发展
唯唯qwe-5 小时前
Day23:动态规划 | 爬楼梯,不同路径,拆分
算法·leetcode·动态规划
做科研的周师兄5 小时前
中国土壤有机质数据集
人工智能·算法·机器学习·分类·数据挖掘
来深圳5 小时前
leetcode 739. 每日温度
java·算法·leetcode
LYFlied6 小时前
WebAssembly (Wasm) 跨端方案深度解析
前端·职场和发展·wasm·跨端