leetcode31下一个排列

题目

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

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

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

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,5,4,3 →1,3,2,4,5
3,2,1 → 1,2,3
1,2,3 → 1,3,2
2,3,1 → 3,1,2
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-permutation

题目分析

这个题没有太多技巧,只要思维好点,能够想出解法,自然可以解决
上面四个测试用例是我精心挑选的,基本可以涵盖所有极端情况
我的技巧:
第一步,从末尾开始找最长倒序
第二步,交换
第三步,反转
下面举例说明技巧

例一 :1,2,5,4,3 →1,3,2,4,5
第一步,从末尾开始找到最长倒序5,4,3
第二步,2和3交换,1,3,5,4,2
第三步,反转5,4,2得到1,3,2,4,5

例二:3,2,1 → 1,2,3
第一步,从末尾开始找到最长倒序3,2,1
第二步,这种完全倒序情况不需交换
第三步,反转即可1,2,3

例三:1,2,3 → 1,3,2
第一步,从末尾开始找到最长倒序3
第二步, 2和3交换,1,3,2
第三步,反转2还是1,3,2

例四:2,3,1 → 3,1,2(我死在这个用例上一次)
第一步,从末尾开始找到最长倒序3,1
第二步, 这时候交换要注意了,1不可以和2交换,要从倒序中找到第一个可以和2交换的数,即3,交换后3,2,1
第三步,反转2,1得到3,1,2

代码

public class NextPermutation {
    public static void main(String[] args) {
        int[] nums = new int[]{2,3,1};
        new NextPermutation().nextPermutation(nums);
        for (int i :nums) {
            System.out.print(i+" ");
        }
    }

    public void nextPermutation(int[] nums) {
        if(null==nums||nums.length<=1)return;
        //从末尾开始找倒序
        int i = nums.length-1;
        int num = nums[i];
        i--;
        while(i>=0&&nums[i]>=num){
            num = nums[i];
            i--;
        }
        //如果i>=0,说明需要交换
        if(i>=0){
            //找出最合适的交换位置
            int len = nums.length-1;
            while(nums[i]>=nums[len]){
                 len--;
            }
            int temp = nums[i];
            nums[i] = nums[len];
            nums[len] = temp;
        }
        //反转 后面的元素
        swap(nums,i+1,nums.length-1);
    }

    private void swap(int[]nums,int i,int j){
        for(int m=i;m<=(i+j)/2;m++){
            int temp = nums[m];
            nums[m] = nums[j-m+i];
            nums[j-m+i] = temp;
        }
    }
}

beat 100% perfect

发布了127 篇原创文章 · 获赞 68 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/LiuRenyou/article/details/102463126