(LeetCode 热题 100) 46.全排列

目录

题目:

题目描述:

题目链接:

思路:

核心思路:

思路详解:

代码:

Java代码:


题目:

题目描述:

题目链接:

46. 全排列 - 力扣(LeetCode)

思路:

核心思路:

dfs

思路详解:

根据全排列和示例我们可以画出如下的搜索树

通过搜索树我们能更好的理解如何使用dfs的具体逻辑来完成题目,因为是全排列,nums里面的每一个数不会重复出现排列,所以我们可以定义布尔类型used数组来标记某个数是否被用过。dfs的参数u表示现在在选第u位数,u从0开始。每次选数时遍历所有数,看哪个数没被用过,选择没用过的数加入到list当中后把该数used标记为true,然后dfs(u+1)继续枚举下一个位置的数。回溯的时候注意恢复现场。dfs的结束条件就是u==n,表明这是其中一个合法的排列,然后将list加入到res中。

这里有两个实际编码容易出错的地方:1、nums是permute方法的参数,在dfs方法中无法直接访问。有两种处理方式一个是将nums作为类的成员变量,另一个是在dfs中传递nums 2、在将list加入res时,不是直接res.add(list)而是res.add(new ArrayList<>(list))新建一个List,不然会出现引用问题

代码:

Java代码:

复制代码
class Solution {
    private int n;
    private boolean[] used;  //默认为false,即所有数都没有被用过
    private List<Integer> list = new ArrayList<>();
    private List<List<Integer>> res = new ArrayList<>();
    private int[] nums;  //要么将nums作为成员变量,要么将nums作为参数传递给dfs

    public List<List<Integer>> permute(int[] nums) {
        this.n = nums.length;
        this.used = new boolean[n];
        this.nums = nums;

        dfs(0);
        return res;
    }

    public void dfs(int u)  //u表示现在在选第u位数,u从0开始
    {
        if(u == n)
        {
            res.add(new ArrayList<>(list));  //避免引用问题,新建一个List
            return;
        }

        for(int i=0;i<n;i++)
        {
            if(!used[i])  //如果某个数没被用过
            {
                list.add(nums[i]);  //选择这个数排列,加入到list中
                used[i] = true;  //将该数used标记改为true
                dfs(u+1);  //继续枚举下一个位置的数

                list.remove(list.size()-1);  //回溯,移除最后一个元素
                used[i] = false;  //回溯,恢复现场
            }
        }
    }
}