题目
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
思路
回溯的入门题,套用回溯模板即可,注意下面的细节
代码
selected 列表在递归的过程中会反复被修改(添加和删除元素),如果直接将 selected 添加到 res,会导致最终 res 中的所有列表对象都是指向同一个 selected 对象,所以结果将是一个错误的全排列列表。
为了解决这个问题,可以通过创建一个新的列表对象,将 selected 的内容复制到该对象中,并将该对象添加到 res 列表中。修改的代码如下:
res.add(new ArrayList<>(selected));
这样每次添加到 res 列表的对象都是一个独立的列表对象,不会受到后续修改的影响,确保得到正确的全排列结果。
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
List<Integer> selectable = new ArrayList<>();
for (int num : nums) {
selectable.add(num);
}
List<Integer> selected = new ArrayList<>();
permutation(selected,selectable);
return res;
}
public void permutation(List<Integer> selected,List<Integer> selectable){
if(selectable.size() == selected.size()){
res.add(new ArrayList<>(selected));//关键
return;
}
for(int i = 0;i<selectable.size();i++){
Integer num = selectable.get(i);
if(selected.contains(num))
continue;
selected.add(num);
permutation(selected,selectable);
selected.remove(num);
}
}
}
回溯模板
function backtrace(已选解集合,每个阶段可选解) {
if (已选解集合满足条件) {
结果集.add(已选解集合);
return;
}
// 遍历每个阶段的可选解集合
for (可选解 in 每个阶段的可选解) {
// 选择此阶段其中一个解,将其加入到已选解集合中
已选解集合.add(可选解)
// 进入下一个阶段
backtrace(已选解集合,下个阶段可选的空间解)
// 「回溯」换个解再遍历
已选解集合.remove(可选解)
}
}