程序是别人的,我几乎没动。惊叹其运行速度,转载一下~
原地址:https://www.jianshu.com/p/42211be17acb
我一开始的思路是用取余,余数小于被除数就说明多除了一次,应该往后退一步,一半递归一半循环,看了他的思路,发现我递归到后面数非常小了,用除法还不如用减法,全都用减法的,清晰好用。
分析:
- 使用
Arrays.sort(candidates);
先排序 - 参数
target
在list
每加入一个数字元素时,值减少,通过对target
的判断,选择操作种类 - 深度优先遍历,当
target
始终大于0时,会一直进行搜索,不断跳入新的递归方法,直到target
小于等于0或数组到达尾部 - 当搜索到达尾部时,通过不断去除
list
最后元素,for循环进入到下一个 i 的深度遍历,来达到全部组合的遍历 flag
用于跳出循环,增加效率,排序后的数组呈升序,当返回此路不通时,for循环后面更大的数也将返回false
,可以直接跳出
程序如下:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> list = new ArrayList<>();
Arrays.sort(candidates);
combinationSumHelp(candidates,result,list,target,0);
return result;
}
public boolean combinationSumHelp(int[] candidates,List<List<Integer>> result,List<Integer> list,int target,int start){
if(target<0){
return false;
}else if(target==0){
List<Integer> temp = new ArrayList<Integer>(list);
result.add(temp);
return false;
}else{
for(int i = start; i < candidates.length ; i++){
list.add(candidates[i]);
boolean flag = combinationSumHelp(candidates,result,list,target-candidates[i],i);
list.remove(list.size()-1);
if(!flag){
break;
}
}
}
return true;
}
}
总结
- 递归方法总是需要大量优化,递归的位置也尤为重要
- 深度优先遍历,其实就是获取所有解的过程,在其中分辨需要的解进行操作
- 对于可变对象的操作需要谨慎,为其重新分配空间可以使其变为不可变对象(没有被增删改)
- 尽量不使用集合来处理问题是数组类题目提升效率的基本操作