Leetcode-31 下一个排列

一、问题描述

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

二、解题思路

在纸上画几个排列就能找到规律了,由于下一个排列肯定是基于后面几位来决定的,因此从后往前扫描数组。

先举几个例子 1,2,3,4 下一个排列1,2,4,3

​ 1,2,4,3 下一个排列1,3,2,4

​ 1,3,4,2 下一个排列1,4,2,3

​ 1,4,3,2 下一个排列2,1,3,4

可以看出,从最后一个位置开始扫描,用一个指针index记录:

1)如果index的元素比index-1位置的元素大,交换index和index-1位置的元素

2)如果index的元素比index-1位置的元素小,更新index指向前一个位置,重复判断index和index-1,直到找到一个index,使得index-1位置的元素比index位置的元素小,标记这个index-1位置,记为pre

​ 从最后一个位置往前扫描数组,直到找到一个比pre位置元素大的最小元素,由于pre右边的元素是递减的,因此从右往左扫描到的第一个比pre位置大的元素即为所求,记为suc。

​ 交换pre和suc位置的元素,并对pre位置后的元素进行排序。

3)注意如果数组是降序排列的即任意位置index-1都比index大,说明没有下一个排列,直接对数组进行排序即可。

第2步的原理:如果数组中从某一位置index开始都是降序的,那么下一个排列一定会更新index-1位置的值,而这个index-1位置的新值一定是后面最小的比index-1位置原来的值大的数,因此交换这两个位置的元素。交换后,后面的元素一定是按照升序排列的,因此排序后面的数组。

三、代码

class Solution {
    public void nextPermutation(int[] nums) {
        if(nums.length==1)return;
        int index=nums.length-1;
        while(index>0 && nums[index-1]>=nums[index]){
            index--;
        }
        if(index==0){
            Arrays.sort(nums);
            return;
        }
        int pre=index-1;//将要被交换的前面的元素
        int suc=nums.length-1;//将要被交换的后面的指针
        while(suc>pre&&nums[suc]<=nums[pre])suc--;
        swap(nums,pre,suc);
        Arrays.sort(nums,pre+1,nums.length);
    }

    public void swap(int[] nums,int i,int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }
}

四、结果

执行时间1ms99.57%
消耗内存40.3M43.75%

五、总结

这道题目想清楚后也不难,在纸上画几个就能有规律了,主要还是要清楚排列变化的规则。

排列数组指定位置后面的元素的方法:
Arrays.sort(int[] nums,int begin,int end);
将nums数组从begin位置开始(包括begin)开始到end(不包括end)位置的元素进行排序。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值