“C++程序员觉得内存管理太重要了,所以一定要自己进行管理;Java/C#程序员觉得内存管理太重要了,所以一定不能自己去管理。”
简直人生态度。
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7] and target 7,
A solution set is:
[
[7],
[2, 2, 3]
]
candidate numbers (C):候选者数字集合
target:目标和
每个候选数字可使用多次 既然这样原集合重不重复就不重要了 用个set就可以了
刷leetcode之后 我发现学会的很重要的一件事:第一念头不是怎么解决问题,而是怎么把大问题转化成小问题,所有,我是说几乎所有,都可以用分治法,比如这道:
非常好 画了十分钟的图
画的过程中思路就会很清晰:
对set排序:
递归方法:
如果target == 0 有解 结束 当前解存入solution set里面
否则:
如果 最小候选数字 < target 无解 结束
否则:
遍历小于target的候选者 去做子问题的递归
贴一个超时的代码:
Stack<Integer> result = new Stack<Integer>();
Set<Stack<Integer>> results = new HashSet<Stack<Integer>>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> listResults = new ArrayList<List<Integer>>();
Set<List<Integer>> setResults = new HashSet<List<Integer>>();
Arrays.sort(candidates);
backTracking(candidates, target);
for(Stack<Integer> stackResult: results){
List<Integer> listResult = stackResult.subList(0, stackResult.size());
listResult.sort((a,b)->a-b);
setResults.add(listResult);
}
setResults.forEach(a->listResults.add(a));
return listResults;
}
public void backTracking(int[] candidates,int target){
if(target == 0) {
Stack<Integer> copy = new Stack<Integer>();
copy.addAll(result);
results.add(copy);
}
else{
if(candidates[0] > target)
return ;
else{
for(int i = 0;i < candidates.length && candidates[0] <= target;i++){
result.push(candidates[i]);
backTracking(candidates, target-candidates[i]);
result.pop();
}
}
}
}
分析一下原因:嗯 图里面232 和 223确实是一种拿法却算了两次
我觉得我应该回去找找皇后那道题做一下 好菜。。
为了避免这种重复 本来我的代码是不避免的 所以232 223都返回 然后再stack 转 list list再sort 再判重复。。。果然前期不想好后期好麻烦。。。
前期如果避免232 223的这种重复:
记录开始位置 23后面只尝试3及3以上的 也就是:回溯的时候记录当前结果路径最大值对应原排序数组的位置 只从该位置开始尝试
Stack<Integer> result = new Stack<Integer>();
List<List<Integer>> results = new ArrayList<List<Integer>>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backTracking(candidates, target,0);
return results;
}
public void backTracking(int[] candidates,int target,int from){
if(target == 0) {
List<Integer> copy = new ArrayList<Integer>();
copy.addAll(result);
results.add(copy);
}
else{
if(candidates[0] > target)
return ;
else{
for(int i = from;i < candidates.length && candidates[0] <= target;i++){
result.push(candidates[i]);
backTracking(candidates,target-candidates[i],i);
result.pop();
}
}
}
}
终于写出了清楚的代码。。真的好菜。。。