Next Permutation(下一个排列)

问题

Given a list of integers, which denote a permutation.

Find the next permutation in ascending order.

Notice

The list may contains duplicate integers.

Have you met this question in a real interview? Yes
Example
For [1,3,2,3], the next permutation is [1,3,3,2]

For [4,3,2,1], the next permutation is [1,2,3,4]

分析

首先要理解题目,对一组数有一个全排列,然后把所有的全排列按升序排列。所以要找的下一个排列就是比这个排列大最少的排列。
想要比当前排列大一点,考虑从右向左查找。找到一个右边比左边大的,我们把左边的小值换一个大值就让这个排列变大了,因为是从右向左,在低位处优先做了,所以保证这个是大得最少的,也就是题目要求的下一排列。当这个排列已经是最大的时候,我们直接循环回去,找到最小的那个排列就可以,其实就是把数组全部翻转。
现在我们解决第一种情况,我们首先从右向左找,找到第一个左边的比右边小的位置,记为i,i+1肯定比i大,这是当然的,i就是这么找到的。
但是i+1右边的比i+1小,i也比i+1小,所以i+1右边的和i的大小就无法确定了。为了找到下一个排列,要求当前排列变大得最少,所以我们需要找到比i大的最小值。我们从数组的尾部开始遍历,找到第一个比i大的值,肯定能找到,最差就是i+1这个位置。找到之后,我们记为k。我们交换k和i上的值。这样之后,i上的值已经变大,然后从i+1到数组的尾部恰好是一个降序。因为要大的得少,所以我们把i+1到尾部再翻转一次。

代码

public class Solution {
    /*
     * @param nums: A list of integers
     * 
     * @return: A list of integers
     */
    public int[] nextPermutation(int[] nums) {
        // write your code here
        for (int i = nums.length - 2; i >= 0; i--) {
            if (nums[i + 1] > nums[i]) {
                for (int j = nums.length - 1; j > i; j--) {
                    if (nums[j] > nums[i]) {
                        int temp = nums[i];
                        nums[i] = nums[j];
                        nums[j] = temp;
                        reverse(nums, i + 1, nums.length-1);
                        return nums;
                    }
                }
            }
        }
        reverse(nums, 0, nums.length - 1);
        return nums;
    }
    private void reverse(int[] nums, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
}

你可能感兴趣的:(Next Permutation(下一个排列))