上一题的升级版, 对代码增加了剪枝操作
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
// 用来保存结果
List<List<Integer>> ls = new ArrayList<List<Integer>>();
// 用来保存数组的集合
List<Integer> numsLs = new ArrayList<Integer>();
// 增强for循环来遍历数组加入到集合中
for (int i : nums) {
numsLs.add(i);
}
// 开始递归
recursion(new ArrayList<Integer>(), numsLs, ls, -1);
return ls;
}
private void recursion(ArrayList<Integer> arrayList, List<Integer> numsLs, List<List<Integer>> ls, int num) {
// 若不为开始, 则添加值进入到arrayList, 然后把值从原集合中移除
if (num != -1) {
arrayList.add(numsLs.get(num));
numsLs.remove(num);
}
// 若集合为空, 说明已经递归完成
if (numsLs.isEmpty()) {
// 此处使用new来添加进入到ls中, 或许不用?
ls.add(new ArrayList<Integer>(arrayList));
return;
}
// 与上一题不同的地方在这, 对递归遍历 进行了剪枝, 此处创建一个set来保存添加过的值
HashSet<Integer> hashSet = new HashSet<Integer>();
for (int i = 0; i < numsLs.size(); i++) {
// 如果将要递归的节点已经在set中的话, 则直接结束此次循环
if (hashSet.contains(numsLs.get(i))) {
continue;
}
// 把即将要递归的节点添加进入到set中
hashSet.add(numsLs.get(i));
// 递归, 此处必须new来传递数值, 不然会传地址值, 传地址的话, 每个节点的操作就会互相影响, 得出的结果就会一团乱
recursion(new ArrayList<Integer>(arrayList), new ArrayList<Integer>(numsLs), ls, i);
}
}
}