Leetcode31. Next Permutation

这题主要是理排列的思路,归纳排列的规则,还挺难的。

看了discuss后才做出来。

public class NextPermutation31 {
    public void nextPermutation(int[] nums) {
        int i = nums.length-2;
        while(i>=0&&nums[i+1]<=nums[i]) {
            i--;
        }
        if(i>=0) {
            int j = nums.length-1;
            while(j>=0&&nums[j]<=nums[i]) {
                j--;
            }
            swap(nums,i,j);
        }
        reverse(nums,i+1);
    }
    private void swap(int[] nums,int i,int j) {
        int temp = nums[i];
        nums[i]=nums[j];
        nums[j]=nums[i];
    }
    private void reverse(int[] nums,int i) {
        int j = nums.length-1;
        while(i<j) {
            swap(nums,i++,j--);
        }
    }
}

13ms,30%.

猛地看有点懵逼,这里说明一下。

在lexicographically条件下,下一个排列应该是相对上个排列更降序一些。即,整体的走向是将升序逐渐变为降序。

比如 12345为升序,下一个是12354,最后两个降序。再下个12435,将4提前,后面的Reverse一下升序,提前操作其实就是和3换位。

所以需要交换和reverse操作,先写出函数来。

然后流程是,倒着找,先找最后的一对相邻的升序的元素a[i]和a[i+1]。这时,a[i]右边都是非升序的(降序和相等),无法再往下排列了,故需要找到比a[i]大的最小的元素,放在i位置上(和a[i]互换)。

找的方法就是从右开始找,找到第一个比a[i]大的数a[j],互换。

之后,右边相当于要成为一个新的排列,故要变为升序,而a[i]a[j]互换后,右边应该正好是降序的(因为右边开始非升序,找的是第一个比a[i]大的数,即a[j]右边都比a[i]小,左边都大,换完依然是非升序),故reverse即可。

看了下8ms答案,思路都是一样的,而且也没做什么优化,所以这样就可以了。

posted @ 2018-12-25 22:02  大胖子球花  阅读(70)  评论(0)    收藏  举报