[LeetCode] 40. 组合总和 II(java实现)dfs
1. 题目
2. 读题(需要重点注意的东西)
思路(dfs):
这种类似于凑组合数的题,可以使用类似排列数字的方法,即dfs。
整体的思路与[LeetCode] 39. 组合总和(java实现)dfs大致相当,在此不再赘述。
唯一需要注意的是: candidates 中的每个数字在每个组合中只能使用一次 ,因此需要对数组排序后再进行判断,方便去重。
3. 解法
---------------------------------------------------解法---------------------------------------------------:
class Solution {
List<List<Integer>> list = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
dfs(candidates,0,target);
return list;
}
public void dfs(int[] candidates,int u,int target){
if(target == 0){
list.add(new ArrayList(path));
return;
}
// 已经遍历到最后一个数
if(u == candidates.length) return;
// 注意:candidates中的每个数字在每个组合中只能使用一次
for(int i = u;i < candidates.length;i++){
// 跳过相同的数
if(i > u && candidates[i] == candidates[i - 1]) continue;
if(target - candidates[i] >= 0){
path.add(candidates[i]);
dfs(candidates,i+1,target - candidates[i]);
path.remove(path.size()-1);
}
}
}
}
可能存在的问题:
问题一:为什么打印出来的结果为[[ ],[ ],…]?
答:
①list.add(new ArrayList(path))
:开辟一个独立地址,地址中存放的内容为path链表,后续path的变化不会影响到list;
②list.add(path)
:将list尾部指向了path地址,后续path内容的变化会导致list的变化。
问题二:List.remove()有哪两种使用方法?
答:
①当传入的值为int型时,删除指定下标的值,如remove(2);
②当传入的值为Object型时,如Integer、String,会删除第一个找到的Object值,如remove(“hello”)。
4. 可能有帮助的前置习题
- [AcWing]842. 排列数字(C++实现)dfs模板题,递归思想的解释
- [LeetCode] 39. 组合总和(java实现)dfs
- [LeetCode] 26. 删除有序数组中的重复项(java实现)
5. 所用到的数据结构与算法思想
6. 总结
① 掌握dfs在排列组合数字方面的应用;
② 注意list.add和list.remove的使用方法;
③ 复习有序数组去重的方法。