力扣热题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;
        }
       
    }
}
相关推荐
裤裤兔1 小时前
利用matlab进行FDR校正的实现方式
数据结构·算法·matlab·多重比较矫正·校正·fdr
子一!!1 小时前
哈希桶,元素插入逻辑实现
算法·哈希算法
敲代码的嘎仔1 小时前
LeetCode面试HOT100——160. 相交链表
java·学习·算法·leetcode·链表·面试·职场和发展
吃着火锅x唱着歌1 小时前
LeetCode 454.四数相加II
算法·leetcode·职场和发展
敲代码的嘎仔1 小时前
LeetCode面试HOT100—— 206. 反转链表
java·数据结构·学习·算法·leetcode·链表·面试
自然语1 小时前
深度学习时代结束了,2025年开始只剩下轮廓
数据结构·人工智能·深度学习·学习·算法
海天一色y1 小时前
Leetcode07-整数反转
算法
im_AMBER1 小时前
Leetcode 66 几乎唯一子数组的最大和
数据结构·笔记·学习·算法·leetcode
Aspect of twilight1 小时前
华为华为AI岗实习面试算法题
算法·华为·面试