回溯
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] -> [ ]