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

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();
                }
            }
        }
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值