这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战
今天周六,需要给自己充充电,做上一题
组合总和
该题出自力扣的39题 —— 组合总和【中等题】
在做题先,需要先叙述关于回溯的相关思路。回溯也就是我们经常在做树的遍历时的深度遍历,dfs。所谓的回溯,也就是一头走到黑,然后再回退,另辟蹊径,再一头走到黑。直到彻底走完。
public void dfs(TreeNode node){
if(node == null)return;
dfs(node.left);
System.out.println(node.val);
dfs(node.right);
}
这就是典型的树的前序遍历,并且用递归的方式,也就是回溯。先一头扎到节点的左子树,直到为空。然后回退,走根节点,再走右子树。
组合总和
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
- 该题最主要的核心就是同一个数字可以无限制被选取;如果抛开这个条件,则可以直接用遍历碾压过去
- 联想到回溯法。把数组转换为树,就很容易能够得出思路
- 先一头扎到黑,每次直接调用dfs方法,index下标 +1
- 再去对比,看是否符合条件
- 最终返回ans
编码
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
List<Integer> combine = new ArrayList<Integer>();
dfs(candidates,target,0,ans,combine);
return ans;
}
public void dfs(int[] candidates,int target, int idx,List<List<Integer>> ans,List<Integer> combine){
if(idx == candidates.length)return;
if (target == 0) {
ans.add(new ArrayList<Integer>(combine));
return;
}
// 直接跳过
dfs(candidates, target,idx + 1, ans, combine );
// 选择当前数
if (target - candidates[idx] >= 0) {
combine.add(candidates[idx]);
dfs(candidates, target - candidates[idx],idx, ans, combine);
combine.remove(combine.size() - 1);
}
}
}