子集
题目:78
- 只不过比组合问题多了一个组合长度
- 毕竟子集啦,不同长度啦
- 再用一个for循环表示组合长度就行
- 递归返回值和参数:这个len就表示长度
private void backTracking(int[] nums, int startIndex, int len)
- 结束条件:长度达到或者一些超出边界
if (path.size() == len) {
res.add(new ArrayList<>(path));
return;
}
if (startIndex >= nums.length || path.size() > len) {
return;
}
- 主方法里这样就行啦
res.add(path);//表示最开始的空集
for (int i = 1; i <= nums.length; i++) {
backTracking(nums, 0, i);//表示每一次循环都是不同的数组长度
}
子集II
题目:90
- 依然是关于去重的问题
- 涉及到去重,最好先给数组排序,这样方便去重,即跳过一段重复数字后,后面再无该数字
- 这里的去重就和之前的(40:数组总和II)一个一样,要么用used[i] 要么用索引跳过
- 这里说一下used数组的逻辑:先跳到重复数字段的最后一个重复数字,比如11111,利用该条件直接跳到11111(最后一个1),然后用这最后一个1。
- 这里的最后一个1,指的是当前层使用过的相同的元素,第一个出现的1在当前层已经用过了,要不然不会有nums[i] == nums[i - 1] && !used[i - 1]的判定条件......应该,毕竟说明used[i-1]已经给用过然后是回溯后的样子了?
- 至于会出现的数组[1,1],两个1是在不同层取到的啦
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]){
continue;
}
path.add(nums[i]);
used[i] = true;
subsetsWithDupHelper(nums, i + 1);
path.removeLast();
used[i] = false;
- 另一个用索引跳过的也是这个意思啦
if ( i > start && nums[i - 1] == nums[i] ) {
continue;//这里跳过的是start啦,说明传来的start已经用过哩
}
递增子序列
题目:491
- 要是递增,看题目,数组里的顺序还不能变,而且会把两个相同的也认识
- 毕竟就是求自增子序列,所以原来的顺序不能变,故去重方法不能照用以前的了
- 方法返回值和参数,因为毕竟是不能重复的,所以还是要有startIndex
- 返回条件:题中说了,大于2就行,不过此时不能返回,因为还要继续把树枝延伸下去,取到这个树枝上的所有节点。如果此时返回了,就都是长度为2的答案了
if (path.size() > 1) {
res.add(new ArrayList<>(path));
}
- 单层递归逻辑:同一父节点下的同层上使用过的元素就不能再使用了 所以used[]数组在回溯方法里创建,代表每一层的元素使用情况,又因为used[]只负责本层,所以不用再把它弄到false。然后还要判定是不是递增的情况
int[] used = new int[201];
for (int i = start; i < nums.length; i++) {
if (!path.isEmpty() && nums[i] < path.get(path.size() - 1) ||
(used[nums[i] + 100] == 1)) continue;
// nums[i] < path.get(path.size() - 1) :当前nums[i]小于单位列表的最后一个,不是递增,跳过
//(used[nums[i] + 100] == 1) :当前数值已经用过了
used[nums[i] + 100] = 1;
path.add(nums[i]);
backtracking(nums, i + 1);
path.remove(path.size() - 1);
}
- 为什么used[]不是代表该索引对应的值有没有用到(int[] used = new int[nums.length];),而是代表数值有没有用到(int[] used = new int[201];)
- 因为给的数组不一定是排序的,如果不是排序的,那么利用索引去重没有意义,毕竟两个一样的数字可能是不连续的,如果用索引去重的话,会出现下面的重复情况
[[4,6],[4,6,7],[4,6,7,7],[4,6,7],[4,7],[4,7,7],[4,7],[6,7],[6,7,7],[6,7],[7,7]]
- 总之就是同层的不能用同一个元素,但是下一层可以和上一层用一样的元素。之前的回溯也是这样,不要因为单个集合里允许有重复数字就弄混,要分清这一层和下一层,即广度和深度的不同