[LintCode] Next Permutation II [Next Permutation]

583 查看

Problem

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).

Example

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

Challenge

The replacement must be in-place, do not allocate extra memory.

Solution

public class Solution {
    public void nextPermutation(int[] nums) {
        int len = nums.length;
        if (nums == null || len == 0) return;
        //从末位向前遍历,(假设循环开始全是倒序排列,如65321)
        for (int i = len - 2; i >= 0; i--) {
            //当第一次出现正序的时候,如465321的4和6
            if (nums[i] < nums[i+1]) {
                //此时从数列末尾向前循环到i,
                //找到第一个比nums[i]大的nums[j]
                int j;
                for (j = len - 1; j >= i; j--) {
                    if (nums[j] > nums[i]) break;
                }
                //交换这两个数,变成564321
                swap(nums, i, j);
                //倒置第i+1位到末位的数为正序排列512346
                reverse(nums, i+1, len-1);
                return;
            }
        }
        //这里return的是完全倒置的排列,如654321,
        //即上面for循环的if情况完全没有出现,for循环没有做过任何操作
        reverse(nums, 0, len-1);
        return; 
    }
    public void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    public void reverse(int[] A, int start, int end) {
        while (left < right) swap(A, start++, end--);
    }
}

简化一下,分别用while循环找i和j,奇怪的是,速度在1ms(10.29%)和2ms(71.29%)之间
public class Solution {
    public void nextPermutation(int[] A) {
        int n = A.length, i = n-2;
        while (i >= 0 && A[i] >= A[i+1]) i--;
        if (i >= 0) {
            int j = n-1;
            while (A[j] <= A[i]) j--;
            swap(A, i, j);
        }
        reverse(A, i+1, n-1);
        return;
    }
    public void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    public void reverse(int[] A, int i, int j) {
        while (i < j) swap(A, i++, j--);
    }
}