46. 全排列

131 阅读1分钟

解法一:用一个boolean数组记录用过的数字

  • 排列问题,下层不能重复使用上层已选的数字
class Solution {
    LinkedList<Integer> path = new LinkedList<>();
    List<List<Integer>> res = new ArrayList<>();
    int size;
    boolean[] visited;//用于记录某个数字是否被访问过,记录index
    
    public List<List<Integer>> permute(int[] nums) {
        size = nums.length;
        visited = new boolean[size];//初始化默认为false
        dfs(nums);
        return res;
    }
    //传入源nums[]
    public void dfs(int[] nums) {
        if (path.size() == size) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (visited[i]) {//同一个分支内,上一层选过的数字本层不能重复使用
                continue;
            }
            path.add(nums[i]);
            visited[i] = true;//该数字已经用过了,本分支下面的层不能再用了
            dfs(nums);
            path.removeLast();//path撤销
            visited[i] = false;//该数字对应的分支dfs完后,visited也要撤销,便于后面数字使用
        }
    }
}

解法二:往下曾拷贝新的候选list

class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    int size;
    public List<List<Integer>> permute(int[] nums) {
        size = nums.length;
        // 数组转List 构建候选集
        List<Integer> candidates = new ArrayList<>();
        for (int x : nums) {
            candidates.add(x);
        }
        dfs(candidates);
        return res;
    }

    public void dfs(List<Integer> candidates) {
        if (path.size() == size) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < candidates.size(); i++) {
            path.add(candidates.get(i));
            List<Integer> newList = new ArrayList<>(candidates);
            newList.remove(i); // 构建新的候选集
            dfs(newList);
            path.remove(path.size() - 1); // 这一支结束,回溯
        }
    }
}