leetcode 力扣 46 全排列

63 阅读1分钟

回溯

class Solution {
    List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> permute(int[] nums) {
        int len = nums.length;
        boolean[] used = new boolean[len];
        dfs(nums, new ArrayList<>(), 0, used, len);

        return res;
    }

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

        for (int i = 0; i < len; i++) {
            if (!used[i]) {
                path.add(nums[i]);
                used[i] = true;

                dfs(nums, path, depth + 1, used, len);

                used[i] = false;
                path.remove(path.size() - 1);
            }
        }
    }
}

典型的回溯模板题,在面试时要想搞清楚递归的每一处细节,还是很难的。这道题画递归树对写代码也没啥帮助。

看下面的代码

for (int i = 0; i < len; i++) {
    if (!used[i]) {
        path.add(nums[i]);
        used[i] = true;

        dfs(nums, path, depth + 1, used, len);

        used[i] = false;
        path.remove(path.size() - 1);
    }
}

回溯总是先执行完dfs()上面的代码,直到for循环完成,再执行dfs()下面的代码。[1, 2, 3] -> [1 ]

发生回溯后,如果for循环还没完成,继续for循环。[1 ] -> [1, 3, 2]

dfs()下面的代码总是最后执行的,所以在这部分恢复现场。[1, 3, 2] -> [ ]