首页 > 代码库 > [LeetCode]31 Next Permutation

[LeetCode]31 Next Permutation

https://oj.leetcode.com/problems/next-permutation/

http://fisherlei.blogspot.com/2012/12/leetcode-next-permutation.html

public class Solution {
    
    public void nextPermutation(int[] num) {
        
        // Solution B
        nextPermutation_Math(num);
        
        // Solution A
        // nextPermutation_AllPerms(num);
    }
    
    ///////////////////////////////////////
    // Solution A: Generate all permutations for num
    // Sort it
    // Find the next one.
    public void nextPermutation_AllPerms(int[] num) {
        
        // All perms
        List<List<Integer>> allperms = new ArrayList<>();
        allperms(num, 0, allperms);
        
        // Sort
        Collections.sort(allperms, new Comparator<List<Integer>>()
        {
            public int compare(List<Integer> a, List<Integer> b)
            {
                int len = a.size();
                for (int i = 0 ; i < len ; i ++)
                {
                    if (a.get(i) != b.get(i))
                    {
                        return Integer.compare(a.get(i), b.get(i));
                    }
                }
                return 0;
            }
        });
        
        // Find
        int pos = allperms.indexOf(listof(num));
        pos = (pos + 1) % allperms.size();
        for (int i = 0 ; i < num.length ; i ++)
        {
            num[i] = allperms.get(pos).get(i);
        }
    }
    
    // See Permutations II
    private void allperms(int[] n, int start, List<List<Integer>> result)
    {
        int len = n.length;
        if (start >= len)
        {
            // A result found.
            result.add(listof(n));
        }
        
        for (int i = start ; i < len ; i ++)
        {
            // If we have any dups from start to i.
            // No need to continue recursion
            // 
            // 注意不要误以为以下两种做法能够去重:
            // (1)最开始先对数组进行排序,以后每次交换时,只要保证当前要交换的元素和前一个元素不同,这种做法是错误的.
            // 虽然开始进行了排序,但是元素的交换会使数组再次变的无序
            // (2)每次进入递归函数permuteRecur时,对从当前索引开始的子数组排序,这种做法也是错误的.
            // 因为每次交换元素后,我们要恢复交换的元素,如果在递归函数内排序,就不能正确的恢复交换的元素。
            
            if (unique(n, start, i))
            // if (n[start] != n[i])
            {
                swap(n, i, start);
                allperms(n, start + 1, result);
                swap(n, i, start);
            }
        }
    }
    
    private boolean unique(int[] n, int start, int end)
    {
        for (int i = start ; i < end ; i ++)
        {
            if (n[i] == n[end])
                return false;
        }
        return true;
    }
    
    ///////////////////////////////////////
    // Solution B: A math 
    // I don‘t know why
    //
    public void nextPermutation_Math(int[] num) {

        if (num == null || num.length <= 1)
            return; // No need continue

        // Step 1, search from right to left.
        // Find the first index break increase.
        //
        // Step 2, search from right to left
        // Find the first index with value > firstindex.
        //
        // Step 3, swap firstindex and secondindex
        //
        // Step 4, reverse all elements after first index.
        
        // Step 1
        int firstindex = -1;
        int len = num.length;
        for (int i = len - 1 ; i > 0 ; i --)
        {
            if (num[i - 1] < num[i])
            {
                firstindex = i - 1;
                break;
            }
        }
        if (firstindex == -1)
        {
            // All decrease.
            // Reverse all
            reverse(num, 0);
            return;
        }
        
        // Step 2
        int secondindex = num.length - 1;
        while (secondindex > firstindex)
        {
            if (num[secondindex] > num[firstindex])
                break;
            secondindex --;
        }
        if (secondindex == firstindex)
            return;     // invalid
            
        
        // Step 3
        swap(num, firstindex, secondindex);
        
        // Step 4
        reverse(num, firstindex + 1);
    }
    
    /////////////////////////////////////
    //
    // Tools
    
    // Reverse num from s(inclusive) to the end
    private void reverse(int[] num, int s)
    {
        int i = s;
        int j = num.length - 1;
        while (i < j)
        {
            swap(num, i, j);
            i ++;
            j --;
        }
    }
    
    private void swap(int[] num, int i , int j)
    {
        int t = num[i];
        num[i] = num[j];
        num[j] = t;
    }
    
    private List<Integer> listof(int[] n)
    {
        List<Integer> toReturn = new ArrayList<>(n.length);
        for (int i : n)
            toReturn.add(i);
        return toReturn;
    }
}


[LeetCode]31 Next Permutation