Leetcode - Next Permutation

原题链接: https://leetcode.com/problems/next-permutation/
[分析] 参考Code Ganker的思路:1)从低位往高位扫描数组,找到第一个小于其右边数字的位置 p;2)对p分两种情况讨论:a) 若 p >= 0, 即当前数组表示的数并非这个数组能表示的最大数,从p 右边下一个数开始往低位(向右)扫描数组,找到第一个不比p大的下标 q,则 q + 1处是p-q之间比 p 位置上的数字大的最小数,交换 p & q + 1,交换后 p 右边的是一个降序数列,逆序之几位 next permutation。 b) 若 p < 0, 则当前为所有排列中的最大值,逆序整个数组得到最小值。 如何理解这个思路的正确性?步骤1找到的p,其后面是一个降序数列,是后面那些数字排列能得到的最大值,也就是后面无论怎么排列都不可能使整个数组值更大,这说明是时候替换这段子序列前面那个领头数字了,从子序列中找一个比当前领头(p位置的数字)大的最小数字作为新领头,子序列再逆序下,这样得到的新排列是比之前排列对应数值大的最小排列。
实现时注意第一个while里头是 >=,因为我们要找到第一个破坏非降序性质的位置,第二个while里头是 >, 因为要通过找到第一个不比p大的数来找到大于 p 的最小数。
[ref]
http://blog.csdn.net/linhuanmars/article/details/20434115?utm_source=tuicool

public class Solution {
    public void nextPermutation(int[] nums) {
        if (nums == null || nums.length < 2)
            return;
        int p = nums.length - 2;
        while (p >= 0 && nums[p] >= nums[p + 1])
            p--;
        if (p >= 0) {
            int q = p + 1;
            while (q < nums.length && nums[q] > nums[p])
                q++;
            int tmp = nums[--q];
            nums[q] = nums[p];
            nums[p] = tmp; 
        } 
        reverse(nums, p + 1);
    }
    public void reverse(int[] nums, int i) {
        int j = nums.length - 1;
        while (i < j) {
            int tmp = nums[j];
            nums[j] = nums[i];
            nums[i] = tmp;
            i++;
            j--;
        }
    }
}

猜你喜欢

转载自likesky3.iteye.com/blog/2232142