[LeetCode] 46.全排列

方法一(采用交换的方法):

public class L46 {
    public void backtrack(int n, ArrayList<Integer> nums, List<List<Integer>> output,int first){
        if(first==n){
            output.add(new ArrayList<Integer>(nums));
        }
        for(int i=first;i<n;i++){
            Collections.swap(nums,first,i);
            backtrack(n,nums,output,first+1);
            Collections.swap(nums,first,i);
        }
    }

    public List<List<Integer>> permute(int[] nums){
        List<List<Integer>> output=new LinkedList<>();
        ArrayList<Integer> nums_lst=new ArrayList<>();
        for(int num:nums){
            nums_lst.add(num);
        }
        int n=nums.length;
        backtrack(n,nums_lst,output,0);
        return output;
    }

}

第二种(太慢了):

class Solution {
    public List<List<Integer>> permute(int[] nums){
        int n=nums.length;
        List<List<Integer>> output=new ArrayList<>(factorial(n));
        if(n==0) return output;
        boolean[] used = new boolean[n];
        List<Integer> path = new ArrayList<>();
        dfs(nums,n,0,path,used,output);
        return output;
    }

    private int factorial(int n){
        int res=1;
        for(int i=2;i<=n;i++){
            res *=i;
        }
        return res;
    }

    private void dfs(int[] nums,int len,int depth,List<Integer> path,boolean[] used,List<List<Integer>> res){
        if(depth==len) {
            res.add(path);
            return;
        }

        for(int i=0;i<len;i++){
            if (!used[i]) {
                // 1、每一次尝试都创建新的变量表示当前的"状态"
                List<Integer> newPath = new ArrayList<>(path);
                newPath.add(nums[i]);

                boolean[] newUsed = new boolean[len];
                System.arraycopy(used, 0, newUsed, 0, len);
                newUsed[i] = true;

                dfs(nums, len, depth + 1, newPath, newUsed, res);
                // 2、无需回溯
            }
        }
    }
}

第三种(目前最快的):采用回溯的方法

public class L46_2 {

    List<List<Integer>> ans=new ArrayList<>();
    boolean[] visited;
    public List<List<Integer>> permute(int[] nums) {
        visited=new boolean[nums.length];
        helper(nums,new LinkedList<>());
        return ans;
    }

    void helper(int[] nums,LinkedList<Integer> list){
        if(list.size()==nums.length){
            ans.add(new ArrayList<>(list));

//path 这个变量所指向的对象在递归的过程中只有一份,深度优先遍历完成以后,因为回到了根结点

//(因为我们之前说了,从深层结点回到浅层结点的时候,需要撤销之前的选择),因此 path 这个变量回到根结点以后都为空。

//在 Java 中,因为都是值传递,对象类型变量在传参的过程中,复制的都是变量的地址。

//这些地址被添加到 res 变量,但实际上指向的是同一块内存地址,因此我们会看到 6 个空的列表对象。

return;
        }

        for(int i=0;i<nums.length;i++){
            if(!visited[i]){
                visited[i]=true;
                list.add(nums[i]);
                helper(nums,list);
                list.removeLast();
                visited[i]=false;
            }
        }
    }
}
原文地址:https://www.cnblogs.com/doyi111/p/12629130.html