力扣:子集2java
流程:
需要树层去重,而树枝不去重,则需要排序后再使用used的数组
设置一个结果集result和路径path和布尔数组used
回溯三部曲:
返回值和参数:返回值为空,参数为数组nums和当前下标startIndex
将path加入结果集中,(否则无法收集最后的一个子集)//这个方法再手机收集所有节点时需要。
结束条件:当startIndex大于等于nums的长度
单层递归逻辑:
for(i=startIndex;i<nums.length;i++)
循环内,节点操作:判断上一个节点是否和节点想相同,并且是否是回溯后的节点,都符合则结束本次循环,进入下一个i的循环。
将节点加入到path中,并将该节点的used赋值为true
递归(nums,i+1)
回溯:当前节点弹出path,并修改当前节点的used为false
代码:
class Solution {
List<List<Integer>> result = new ArrayList<>();//结果集
LinkedList<Integer> path = new LinkedList<>();//当前路径
public List<List<Integer>> subsetsWithDup(int[] nums) {//主函数
Arrays.sort(nums);//对数组nums排序
used = new boolean[nums.length];//对used数组创建对象
ziji2(nums,0);//递归
return result;
}
boolean[] used;//是否使用中数组
public void ziji2(int[] nums,int startIndex){//递归函数
result.add(new ArrayList(path));//先将path输入result
if(startIndex>=nums.length){//结束条件:开始下标大于等于数组长度
return;
}
for(int i=startIndex;i<nums.length;i++){//i赋值为开始下标
if(i>0&&nums[i]==nums[i-1]&&used[i-1] == false){//树层去重
continue;
}
path.add(nums[i]);//路径加入num[i]
used[i]=true;//对当前节点的used赋值为true
ziji2(nums,i+1);//递归下一层
path.removeLast();//回溯:弹出当前节点
used[i] = false;//used赋值为false
}
}
}