• [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;
                }
            }
        }
    }
  • 相关阅读:
    2020年3月22日
    2021年3月21日
    2021年3月20日
    人件集阅读笔记02
    2021年3月19日
    2021年3月18日
    2021年3月17日
    2021年3月16日
    2021年3月15日
    梦断代码阅读笔记01
  • 原文地址:https://www.cnblogs.com/doyi111/p/12629130.html
Copyright © 2020-2023  润新知