Next Permutation

来源:互联网 发布:产业结构不断优化 编辑:程序博客网 时间:2024/05/17 22:10

原题:

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, do not allocate 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,31,3,2
3,2,11,2,3
1,1,51,5,1

即给定一个字符串数组,这些数组的元素能自由排列成数字,对数组进行修改,使得新数组连起来形成的数字比原数组连起来组成的数字大且最接近。即增大且增量最小。如果给定的数组是最大的(里面元素恰好从大到小排列的),就返回最小值。


思考过程:

这道题比较难在于用人脑如何解决这个问题。要想增大而且增量小,就要从低位着手。举例才能说明白:对于13421,必须找到恰到好处的那一位,否则找高了会导致增量太大,恰到好处的一位满足什么样的条件呢。这道题的3,可以换成4,这样就增加了,同时对后面调整(这很重要),变成14123。可以发现,恰到好处的一位满足:他的后面有有比他大的数。


解题思路:

分三步:

找到恰到好处的那一位(很简单):从小位开始遍历,发现哪一位比后一位小,那这一位就是入手点了。

恰到好处那一位换成后面比它大且最接近的数字:后面的数字是排好序的,可以一个个去比较。我的方法是把遍历过的数字存到哈希表里,如果恰到好处的那一位是n,则取哈希表找n+1,n+2一直到n的后一位(它比n大)。

最后排序:这一位换了之后,后面的要从小到大排列才能保证增量最小,就像14123.


结果代码:

public void nextPermutation(int[] nums) {        Map<Integer,Integer> hasMap = new HashMap<>();//存放已经遍历过的数        int length = nums.length;        if (length <= 1) return;        hasMap.put(nums[length - 1],length - 1);        for (int i = length - 2;i >= 0;i--) {            if (nums[i] < nums[i + 1])                for (int j = nums[i] + 1; j <= nums[i + 1]; j++) {//通过哈希表循环寻找比nums[i]大且与nums[i]最接近的数替代它。                    if (hasMap.containsKey(j)) {                        nums = swap(nums,i,hasMap.get(j));                        nums = wholeSwap(nums,i + 1);                        return;                    }                }            else if (!hasMap.containsKey(nums[i]))hasMap.put(nums[i],i);        }        nums = wholeSwap(nums,0);    }    public int[] swap(int[] nums,int i,int x){//交换数字第i个和第x个数字。        int k = nums[i];        nums[i] = nums[x];        nums[x] = k;        return nums;    }    public int[] wholeSwap(int[] nums,int begin) {//数组从begin开始,后面和前面1交换顺序。        int length = nums.length;        for (int i = begin;i < (begin + length + 1) / 2;i++)            swap(nums,i,length - 1 - i + begin);        return nums;    }

原创粉丝点击