https://oj.leetcode.com/problems/permutations/

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


public class Solution {
    
    // Assumes all input numbers are unique
    
    public List<List<Integer>> permute(int[] num) 
    {
        // Solution A:
        // return permute_Insertion(num);
        
        // Solution B:
        // return permute_SwapRecursively(num);
        
        // Solution C:
        return permute_NP(num);
    }
    
    ////////////////////
    // Solution C: Swap Recursively:
    //
    private List<List<Integer>> permute_NP(int[] num)
    {
        List<List<Integer>> result = new ArrayList();
        boolean[] used = new boolean[num.length];
        permute_NPhelp(num, used, new ArrayList<Integer>(), result);
        return result;
    }
    
    private void permute_NPhelp(int[] num, boolean[] used, List<Integer> items, List<List<Integer>> result)
    {
        int len = num.length;
        if (items.size() == len)
        {
            result.add(new ArrayList<>(items));
            return;
        }
        
        for (int i = 0; i < len ; i ++)
        {
            // Only use those unused chars.
            // Otherwise, need to input a list of int can be used.
            if (used[i])
                continue;

            used[i] = true;
            items.add(num[i]);
            
            permute_NPhelp(num, used, items, result);
            
            used[i] = false;
            items.remove(items.size() - 1);
        }
    }
    
    ////////////////////
    // Solution B: Swap Recursively:
    //
    // swap 0-0, 0-1, 0-2, 0-3, ..., 0-k
    // swap 1-1, 1-2, ... 1-k
    // swap 2-2 ...
    // ...
    // swap k-k
    public List<List<Integer>> permute_SwapRecursively(int[] num)
    {
        List<List<Integer>> result = new ArrayList();
        perm(0, num, result);
        return result;
    }

    private void perm(int start, int[] num, List<List<Integer>> result)
    {
        int len = num.length;
        if(start >= len)
        {
        	List<Integer> tmp = new ArrayList<>(num.length);
        	for(int n : num)
        	    tmp.add(n);
        	result.add(tmp);
        	return;
        }
        
        for(int i = start ; i < len ; i ++)
        {
            swap(num, start, i);
        	perm(start + 1, num , result);
        	swap(num, start, i);
        }
    }
    
    private void swap(int[] A, int i, int j)
    {
        int tmp = A[i];
    	A[i] = A[j];
    	A[j] = tmp;
    }
        
    ////////////////////
    // Solution A: Insertion:
    //
    // n = 1
    //      1
    //
    // n = 2
    //      2,1
    //      1,2
    //
    // n = 3
    //      3,2,1
    //      2,3,1
    //      2,1,3
    //      3,1,2
    //      1,3,2
    //      1,2,3
    //
    // 已知 n-1 集合,对每一个元素,在所有可能出插入数字n。   
    //
    // Bad point:
    // If the input numbers contains dups, need to use Set<Set<Integer>> to avoid dups.
    public List<List<Integer>> permute_Insertion(int[] num) {
        
        List<List<Integer>> toReturn = new ArrayList<>();
        if (num == null || num.length == 0)
            return toReturn;
            
        // Insert result when length = 1
        toReturn.add(Collections.singletonList(num[0]));
        for (int i = 1 ; i < num.length ; i ++)
        {
            List<List<Integer>> newresults = new ArrayList<>();
            for (List<Integer> lastr : toReturn)
            {
                for (int j = 0 ; j <= lastr.size() ; j++)
                {
                    List<Integer> newr = new ArrayList<>(lastr);
                    newr.add(j, num[i]);
                    newresults.add(newr);
                }
            }
            toReturn = newresults;
        }
        return toReturn;
    }
}