力扣热题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;
        }
       
    }
}
相关推荐
To_OC1 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥2 小时前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程
地平线开发者3 小时前
Transformer模型部署之性能优化指南
算法
地平线开发者3 小时前
人在途中:从“编译失败”到“模型可落地”——CUDA 自定义算子
算法·自动驾驶
半个落月6 小时前
从递归到快速排序:用 JavaScript 把分治思想讲明白
javascript·算法·面试
小月土星7 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
javascript·算法·面试
小月土星7 小时前
JavaScript 递归入门:从 1 到 n 求和,再到数组扁平化
javascript·算法·面试
To_OC1 天前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
鱼鱼不愚与1 天前
《原来如此 | 第01期:为什么导航软件能预测红绿灯倒计时?》
算法