46. 全排列(无重复数字)

这是无重复数字的全排列。
注意递归函数中的循环(循环起始位置)和used[]数组的使用

class Solution {
    //dfs和回溯
    LinkedList<List<Integer>> res=new LinkedList<>();
    LinkedList<Integer> path =new LinkedList<>();
    boolean[] used;
    int len=0;
    public List<List<Integer>> permute(int[] nums) {
       len=nums.length;
       used=new boolean[len];
        dfs(nums);
        return res;
    }
    void dfs(int[] nums){//把没有被访问过的节点加入Path
        if(path.size()==len){//显示使用长度记录当前路径长度比访问path.size()要快
            res.add(new LinkedList<>(path));
            return;
        }
       for(int i=0;i<len;i++){
           if(used[i]==false){
             path.add(nums[i]);
             used[i]=true;
             dfs(nums);
             used[i]=false;
             path.removeLast();
           }
           
       }
    }
}

还学习了交换法,不用申请used[]数组。但是看了看,好像空间也没节省多少啊。可能是因为为了转换成List要将int转换成Integer吧...

class Solution {
    //交换法
    LinkedList<List<Integer>> ans=new LinkedList<>();
    Integer[] arr;
    public List<List<Integer>> permute(int[] nums) {
      arr=new Integer[nums.length];
      int k=0;
      for(int num:nums){
          arr[k]=num;
          k++;
      }
      dfs(0);
      return ans;
    }
    void dfs(int cur){//固定cur位置,cur之后的每个元素都来这个位置。
    //用交换实现这个目的。循环遍历cur及其之后的每个元素。实现枚举n种可能
    //递归实现,固定cur后,再固定下一个位置,同样的思路,枚举n-1种可能
    //数字交换后乱了怎么办,其实具体数在哪个位置不重要,重要的是固定一个数。和数字本身无关
    //即使去重操作事先对数组排序,交换后乱了也不重要,重要的是固定一个数
    //排序是为了剪枝(提前终止递归)
        if(cur==arr.length-1){
           ans.add(Arrays.asList(Arrays.copyOf(arr,arr.length)));
           return;
        }
        

        for(int i=cur;i<arr.length;i++){
            swap(cur,i);
            dfs(cur+1);//固定cur位置后,再看下一个位置
            //恢复。递归退出到这里,以nums[cur]为起点的情况递归完了。要恢复起始状态
            swap(cur,i);
        }

    }
    void swap(int pos1,int pos2){
        Integer tmp=arr[pos1];
        arr[pos1]=arr[pos2];
        arr[pos2]=tmp;

    }
}
posted @ 2021-04-24 19:08  wsshub  阅读(209)  评论(0)    收藏  举报