这两题非常相似,只有少量修改,所以放到一起
第一反应
递归,比如示例1,[2,3,6,7] target=7,我的想法是依次从target中减去一个待选数(比如7-2=5),然后对得到的数字再递归调用本体函数。
如果要优化的话,可以考虑对于得到的结果存进数组,以避免反复调用某个target浪费。
看看题解
当做一个树状图的搜索。每一个选择分支都有选择这个数字、不选这个数字两种,如果不选这个数字就把指针移动到下一个数字
看完题解再想
是不是,比如说树状图的搜索,如果在比如左侧的第一个分支表示选择2,在右侧的其他分支就不用考虑选择2的情况了?
复习java
遍历list
for(String value:list){
System.out.println(value);
}
提交通过
我感觉做的还挺漂亮的
class Solution {
public int[] candidates;
public int len;
public List<List<Integer>> ans = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
this.candidates = candidates;
this.len = candidates.length;
dfs(target, new ArrayList<>(), candidates[0]);
return ans;
}
/*
candidates 是作为不变的公共输入信息
target 在不同的节点可能有不同的数值
head 为当前节点所包含的头部数字串,这个节点的子节点所导出的结果必定包含这个head
bound 为边界,candidate中小于bound的数字不会被选择(以防止重复)
*/
public void dfs(int target, List<Integer> head_org, int bound){
List<Integer> head = copyList(head_org);
for(int i = 0 ; i < len ; i++){
if(candidates[i] < bound){
continue;
}
if(candidates[i] < target){
List<Integer> head_temp = copyList(head);
head_temp.add(candidates[i]);
dfs(target - candidates[i] , head_temp, candidates[i]);
}else if(candidates[i] == target){
head.add(candidates[i]);
ans.add(head);
return;
}else{
return;
}
}
}
public List<Integer> copyList(List<Integer> list1){
List<Integer> newList = new ArrayList<>();
for(int value:list1){
newList.add(value);
}
return newList;
}
}
第一反应
上面那题稍微改一下就行。和前一题的差别就在于,一个数字只能用一次。那么把递归搜索的bound参数改一下,之前是数值,现在是第几个数(index),并且不能同一个数用多次(再次调用dfs的时候把i+1)。为了防止同一个数字使用多次,确定本次递归所选择的candidates的时候要用moveToNextIndex(找出下一个不同的数字),而在本次递归选择完成后需要找下一次递归的时候用i+1,这两个是不同的。
提交通过
class Solution {
public int[] candidates;
public int len;
public List<List<Integer>> ans = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
this.candidates = candidates;
this.len = candidates.length;
dfs(target, new ArrayList<>(), 0);
return ans;
}
/*
candidates 是作为不变的公共输入信息
target 在不同的节点可能有不同的数值
head 为当前节点所包含的头部数字串,这个节点的子节点所导出的结果必定包含这个head
bound 为边界,修改这里,避免重复使用数字
*/
public void dfs(int target, List<Integer> head_org, int bound){
// System.out.println("start dfs");
List<Integer> head = copyList(head_org);
for(int i = bound ; i < len ; i = moveToNextIndex(i)){
// System.out.println("i = " + i + " ; bound = " + bound + " ; target = " + target + " ; stack = " + head.size());
if(candidates[i] < target){
List<Integer> head_temp = copyList(head);
head_temp.add(candidates[i]);
dfs(target - candidates[i] , head_temp, i+1);
}else if(candidates[i] == target){
head.add(candidates[i]);
ans.add(head);
// System.out.println("add answer");
return;
}else{
// System.out.println("exit dfs");
return;
}
}
}
public List<Integer> copyList(List<Integer> list1){
List<Integer> newList = new ArrayList<>();
for(int value:list1){
newList.add(value);
}
return newList;
}
public int moveToNextIndex(int i){
int temp = candidates[i++];
while(i < len && temp == candidates[i]){
i ++;
}
return i;
}
}