码迷,mamicode.com
首页 > 其他好文 > 详细

31. Next Permutation

时间:2020-02-19 00:57:15      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:最大的   交换   运行   res   only   perm   which   stream   ted   

1.题目描述

英文版:

Implement next permutation, which rearranges numbers into the

lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible

order (ie, sorted in ascending order).

The replacement must be in-place and use only constant extra memory.

Here are some examples. Inputs are in the left-hand column and its

corresponding outputs are in the right-hand column.

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

中文版:

实现找到下一个排列的算法,按照字典顺序将数字重新排列为下一个更大的数字排列。

如果不存在这样的一个排列,那么必须重新把数字升序排序。

这里有一些例子,输入左手边的列,然后正确输出右手边的列。

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

2.解法

2.1 解法1

思路:

这一题不能使用暴力破解法了,非常的难受,但是做题还是得继续呀。
这道题就通过举例子来讲解思路吧。
对于1,2,3,5,4来说,因为1,2,3,5,4并不是1开头的所有全排列中字典序最大的一个,所以它的下一个全排列的第一个数字仍然是1。
我们只需要考虑2,3,5,4的下一个全排列是多少即可。同理,2,3,5,4的下一个全排列的第1个数字一定是2,所以我们只需要求解3,5,4的下一个全排列。
对于3,5,4来说,它已经是所有3开头的全排列中字典序最大的一个了(3,5,4>3,4,5),所以需要发生“进位”的操作。
即令3变为字典中的下一个元素4,然后将剩下的数字从小到大排列,即3,5,也就是说3,5,4的下一个全排列是4,3,5。
抽象的来说,如果对于一个全排列a1,a2,a3,...,ak来说,如果满足a1 < a2 ≥ a3 ≥ a4 ... ≥ ak(所有a1开头的全排列中字典序最大的情况),就说明这个全排列的下一个全排列不能再由a1开头,而是a1在字典中的下一个元素aj(即最小的满足aj > a1且2 ≤ j ≤ k的aj),由于任何aj开头的全排列都大于a1开头的全排列,所以我们寻找的全排列是aj开头的最小的全排列。

这道题目的做法变成了在给出的全排列中,寻找一个p,要求其满足ap < ap+1 ≥ ap+2 ≥ ap+3 ... ≥ an,然后只需将ap变成ap+1..an中最小的大于ap的数字,然后将剩下的数字按照从小到大的顺序放置即可

注意,对于不存在这样的i时,即a1>=a2>=a3>=...>=an,我们要注意进行特殊处理。

   public static int[] nextPermutation(int[] nums) {
        // 找到 a[i] < a[i+1] >= a[i+2] >= a[i+3]... >= a[i+n]
        // 例如 1,2,3,5,4 中的 5 符合
        int k = 0;
        for(int i = nums.length - 1;i > 0;i-- ){
            if(nums[i] > nums[i-1]){
                k = i;  //将i的位置记下来。 5 的位置记下来
                break;
            }
        }

        if(k == 0){ //如果不存在,例如 5,4,3,2,1 则直接倒置
            Arrays.sort(nums);
        }else { //存在

            //找到k后面大于k-1位置且是最小的数的位置
            int l = k;
            for(int j = k+1 ;j < nums.length;j++){
                if(nums[j] > nums[k-1]){
                    l = j;
                }
            }

            //将k后面大于k-1位置且是最小的数与k-1位置的数交换
            //如果上面的循环不走。如 1,2。则将1,2交换位置
            int tem = nums[k-1];
            nums[k-1] = nums[l];
            nums[l] = tem;

            Arrays.sort(nums,k,nums.length);
        }

        return nums;
    }

在LeetCode上运行的结果:

技术图片

3.测试

在本地,我只是简单写了一个main函数来对它进行测试。但是这些代码都是在LeetCode上运行通过了的。

    public static void main(String[] args) {
        int[] nums = {1,3,2};
        nums = nextPermutation(nums);
        Arrays.stream(nums).forEach(System.out::println);
    }
欢迎关注个人公众号,可直接扫描以下二维码或微信搜索“阿毛聊技术”。

技术图片

31. Next Permutation

标签:最大的   交换   运行   res   only   perm   which   stream   ted   

原文地址:https://www.cnblogs.com/limaodeng/p/12329489.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!