31. 下一个排列

题目描述:

整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
给你一个整数数组 nums ,找出 nums 的下一个排列。
必须原地修改,只允许使用额外常数空间。

示例:
在这里插入图片描述

我刚开始读完题目一脸懵逼。为了防止大家和我一样,我就给大家翻译翻译题目说了啥。

题干的意思是:找出这个数组排序出的所有数中,刚好比当前数大的那个数
比如当前 nums = [1,2,3]。这个数是123,找出1,2,3这3个数字排序可能的所有数,排序后,比123大的那个数 也就是132
如果当前 nums = [3,2,1]。这就是1,2,3所有排序中最大的那个数,那么就返回1,2,3排序后所有数中最小的那个,也就是1,2,3 -> [1,2,3]

按照这个思路,我们继续向下思考,刚好比当前数大的数,那么我们一定是从位数最低的开始去找,即从后面开始找,找的方法也很简单,我以排列[4,5,2,6,3,1]为例,我们先确定第一个位置i,使得i<i+1
i刚开始指向1,i-1指向3,很明显3>1不符合,我们让i–,此时i指向3,i-1指向6,6>3也不符合。
继续让i–,此时的i指向6,i-1指向2<6,符合我们的要求,此时我们找的第一个数2已经确定,我们下面再继续找,找到第二个数,使之与2交换,还是从最低位去找,很明显3刚好符合,我们将2,3交换,最后的结果为:[4,5,3,6,2,1]

最后一步:排序,我们没有动[4,5,2,6,3,1]中2前面的数,所以不用管,只需从2后面排序,使之升序即可。

代码如下:(PS:Java版)

    public void nextPermutation(int[] nums) {
        int length = nums.length;
        if (length <= 1) return;
        //倒序查找第一个元素的下标
        boolean sig = false;//判断是否找到能够交换的值
        int i = length - 1;
        for (; i >= 1; i--) {
            if (nums[i - 1] < nums[i]) {
                sig = true;
                break;
            }
        }
        i -= 1;
        if (!sig) {//说明未交换
            Arrays.sort(nums);
            return;

        }
        //找第二个元素即第一个大于i的元素
        int j = length - 1;
        for (; j >i; j--) {
            if (nums[j] > nums[i]) {
                break;
            }
        }
        //交换i,j
        int t = nums[i];
        nums[i] = nums[j];
        nums[j] = t;
        //重新对i+1之后的元素排序
        int[] nu = new int[length - i - 1];
        int index = 0;
        for (int k = i + 1; k < length; k++) {
            nu[index++] = nums[k];
        }
        Arrays.sort(nu);
        index = 0;
        for (int k = i + 1; k < length; k++) {
            nums[k] = nu[index++];
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZNineSun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值