每日一道Leetcode - 31. 下一个排列

在这里插入图片描述
参考官方题解:

之前按照一个C++大佬解法改写Java直接超时了,还是要少定义不必要的变量。

“下一个排列”:主要就是要找到当前数字组合的下一个更大的一个数字组合,比如123,对于三个值【1,2,3】下一个更大的数排列起来就是【1,3,2】也就是‘132’

主要思路就是:

  • 先从后往前找到第一个相邻的两个数字,满足前小后大的要求,比如1234653,很明显刚开始的(5,3)(6,5)不满足要求,指针往前移,找到第一个前小后大的数字对(4,6) 。
  • 对于4之后的数字【653】我们要从后往前找到第一个比4大的数字,这样保证是下一个最大的数字,数字3不行pass,找到5比4大,交换4和5,最后四位数得到【5643】。
  • 这时候其实还是不能保证是下一个最大,因为【4653】下一个最大肯定要是首个数字变大,后面小的情况,也就是【5346】,很明显,对于我们上一步得到的【5643】这里要对后面的数字【643】进行排序,让那个后面的数字升序排序【346】,这样就满足了下一个最大的排序啦。(可以发现后面的数字是一个逆序排的,所以我们只需要倒置数字就好了)
  • 当然要注意的是,如果找不到前小后大的情况,直接就不满足了,排序就好了。

代码如下:

class Solution {
    public void nextPermutation(int[] nums) {
        // i: 从倒数第二个节点开始
        // 找到第一个相邻的对,满足nums[i]<nums[i+1]
        int i = nums.length-2;
        while(i>=0 && nums[i]>=nums[i+1]){
            i--;
        }
        // 需要判断是不是已经遍历完了(此时i<0)都没有找到这样的相邻对【小,大】
        // such as: 3,2,1 → 1,2,3
        // k: 初始为数组最后一个值 从[i+1,k]找到一个比较小的数k,使(i,k)对满足nums[i]<nums[k]
        int k = nums.length-1;
        if(i>=0){
            while(k>=i+1 && nums[i]>=nums[k]){
                k--;
            }
            // 找到k之后,交换i和k
            swap(nums,i,k);
        }
        // 对i之后的数组进行从小到大升序排列,因为后面是逆序,所以只需要转置即可
        reverse(nums,i+1);
    }
    public void swap(int[] nums,int i,int j){
        int temp = nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }
    public void reverse(int[] nums, int s){
        int left = s;
        int right = nums.length-1;
        while(left<right){
            swap(nums,left,right);
            left++;
            right--;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值