leetcode 39. Combination Sum

“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之后 我发现学会的很重要的一件事:第一念头不是怎么解决问题,而是怎么把大问题转化成小问题,所有,我是说几乎所有,都可以用分治法,比如这道:
leetcode 39. Combination Sum_第1张图片
非常好 画了十分钟的图
画的过程中思路就会很清晰:

set排序:
递归方法:
        如果target == 0 有解 结束 当前解存入solution set里面
        否则:
            如果 最小候选数字 < target 无解 结束
            否则:
                遍历小于target的候选者 去做子问题的递归 

贴一个超时的代码:

Stack result = new Stack();
    Set> results = new HashSet>();

    public List> combinationSum(int[] candidates, int target) {
        List> listResults = new ArrayList>();
        Set> setResults = new HashSet>();
        Arrays.sort(candidates);
        backTracking(candidates, target);
        for(Stack stackResult: results){
            List 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 result = new Stack();
    List> results = new ArrayList>();

    public List> 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 copy = new ArrayList();
            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();
                }
            }
        }
    }

终于写出了清楚的代码。。真的好菜。。。

你可能感兴趣的:(leetcode)