2

题目要求

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,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

翻译过来就是说,输入一个整数数组,该整数数组按照下标顺序代表一个数字,例如[1,2,3]代表整数123,要求改变数组中元素的顺序,找到比当前数字大的生成数中的最小值。如果当前数字代表的整数值已经是所有排列组合中的最大值,则返回当前数字组成的最小值。

思路分析

如何才能找到一个值,不是过大也不是过小呢?其实,找到这几个数字所有排列组合的可能性,然后再和当前数字一一进行比较其实也是一个思路。可是这意味着大量无用的数字的生成和比较。想要知道如何生成所有排列组合结果,可以参考我的这篇博客
换句话说,我们要尽量用最少的比较的到最小的结果。一个数字中的各个位上的数如何调整顺序才能获得一个最小的更大值。首先,可以将低位移到高位,只要低位的数字比高位上的数字大。但是,为了确保的到尽可能小的最大值,一定要将移动的位确保越小越好。其次,要保证移动之后,高位以后的值为最小值。
综上所述,思路如下

  1. 由最低位(下表为nums.length-2)开始,由低往高遍历,找到可以进行替换的最小位。
  2. 可以替换的条件是,比当前位低的位上存在一个数,该数比当前位上的值大,且不存在另一个比该值小且比当前位上值大的数
  3. 替换数值后,该进行替换的位后序的位上的值应当保证为最小值。

例如[1,3,2],将百位上的值和个位上的值替换以后,还要保证百位以后的值为最小值,所以最后的结果为[2,1,3]

实现代码如下

    public void nextPermutation(int[] nums) {
        for(int i = nums.length - 2 ; i>=0 ; i--){
            //寻找可以替换的最低位
            for(int j = i+1 ; j<nums.length ; j++){
                if(nums[i]<nums[j]){
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                    //确保替换位的后续位的值最小
                    Arrays.sort(nums, i+1, nums.length);
                    return;
                }
            }
            //若当前位不可替换,则自当前位开始排序,以保证下一位可以在不进行完整遍历的前提下找到最小的更大值
            Arrays.sort(nums,i,nums.length);
        }
    }

clipboard.png
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~


raledong
2.7k 声望2k 粉丝

心怀远方,负重前行