leetcode 39. Combination Sum

来源:互联网 发布:mac log4j的输出路径 编辑:程序博客网 时间:2024/05/21 10:17

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

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

0 0
原创粉丝点击