组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!
78. 子集
https://www.programmercarl.com/0078.%E5%AD%90%E9%9B%86.html
从图中红线部分,可以看出遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合
求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。
class Solution {List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果public List<List<Integer>> subsets(int[] nums) {if (nums.length == 0){result.add(new ArrayList<>());return result;}subsetsHelper(nums, 0);return result;}private void subsetsHelper(int[] nums, int startIndex){result.add(new ArrayList<>(path));//「遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合」。if (startIndex >= nums.length){ //终止条件可不加return;}for (int i = startIndex; i < nums.length; i++){path.add(nums[i]);subsetsHelper(nums, i + 1);path.removeLast();}}}
90. 子集 II
结合子集问题和组合问题中的去重数组即可完成
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
private void backTracking(int[] nums,int startIndex){
result.add(new ArrayList<>(path));
if (startIndex >= nums.length){
return;
}
for (int i = startIndex; i < nums.length; i++) {
if (i > startIndex && nums[i] == nums[i-1]){//去重
continue;
}
path.add(nums[i]);
backTracking(nums,i+1);
path.remove(path.size() - 1);
}
}
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
backTracking(nums,0);
return result;
}
}
491. 递增子序列
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
private void backTracking(int[] nums, int startIndex) {
if (path.size() > 1) {//因为题目要求递增子序列大小至少为2
result.add(new ArrayList<>(path));
}
if (startIndex >= nums.length) {
return;
}
int[] used = new int[201];
for (int i = startIndex; i < nums.length; i++) {
if (!path.isEmpty() && nums[i] < path.get(path.size() - 1) ||
(used[nums[i] + 100] == 1)){
continue;
}
used[nums[i] + 100] = 1;
path.add(nums[i]);
backTracking(nums, i + 1);
path.remove(path.size() - 1);
}
}
public List<List<Integer>> findSubsequences(int[] nums) {
backTracking(nums, 0);
return result;
}
}
//法二:使用map
class Solution {
//结果集合
List<List<Integer>> res = new ArrayList<>();
//路径集合
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
getSubsequences(nums,0);
return res;
}
private void getSubsequences( int[] nums, int start ) {
if(path.size()>1 ){
res.add( new ArrayList<>(path) );
// 注意这里不要加return,要取树上的节点
}
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=start ;i < nums.length ;i++){
if(!path.isEmpty() && nums[i]< path.getLast()){
continue;
}
// 使用过了当前数字
if ( map.getOrDefault( nums[i],0 ) >=1 ){
continue;
}
map.put(nums[i],map.getOrDefault( nums[i],0 )+1);
path.add( nums[i] );
getSubsequences( nums,i+1 );
path.removeLast();
}
}
}

