Combination Sum
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.
- Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
- 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]
https://leetcode.com/problems/combination-sum/
第一遍的代码如下,写的时候就不是很满意,套了三层循环。
思路就是粗暴迭代,拿题目的例子来说,7可以是2+5,3+4,6+1和7。然后里面的5就递归调用combinationNumber(5), 4调用combinationNumber(4)。
虽然AC了但是624ms相当不理想,别的OJ可能就TLE了,主要是有太多重复的情况,要花时间去剔除掉。
然后去看了官方攻略http://articles.leetcode.com/2010/09/print-all-combinations-of-number-as-sum.html
说了一堆有的没的,我理解了一下其实就是dfs,只不过每个节点可以重复走。
注意到1. 比如递归到3的时候,不要再回去找包含2的结果,因为会有重复的情况。
2.不剪枝就超时或者堆栈爆炸......
旧版:
1 /** 2 * @param {number[]} candidates 3 * @param {number} target 4 * @return {number[][]} 5 */ 6 var combinationSum = function(candidates, target) { 7 candidates.sort(sorting); 8 return combinationNumber(target); 9 10 function combinationNumber(num){ 11 var res = []; 12 for(var i = 0; num - candidates[i] >= 0; i++){ 13 if(candidates[i] === num){ 14 res.push([num]); 15 } 16 var tmpArr = combinationNumber(num - candidates[i]); 17 if(tmpArr.length !== 0){ 18 for(var j in tmpArr){ 19 tmpArr[j].push(candidates[i]); 20 tmpArr[j].sort(sorting); 21 var hasArr = false; 22 for(var k in res){ 23 if(isSameArray(res[k], tmpArr[j])){ 24 hasArr = true; 25 break; 26 } 27 } 28 if(!hasArr){ 29 res.push(tmpArr[j]); 30 } 31 } 32 } 33 } 34 return res; 35 } 36 function sorting(a, b){ 37 if(a > b){ 38 return 1; 39 }else if(a < b){ 40 return -1; 41 }else{ 42 return 0; 43 } 44 } 45 function isSameArray(a, b){ 46 if(a.length !== b.length){ 47 return false; 48 } 49 for(var i in a){ 50 if(a[i] !== b[i]){ 51 return false; 52 } 53 } 54 return true; 55 } 56 };
新版:
1 /** 2 * @param {number[]} candidates 3 * @param {number} target 4 * @return {number[][]} 5 */ 6 var combinationSum = function(candidates, target) { 7 var res = []; 8 candidates.sort(sorting); 9 dfs(0, 0, []); 10 return res; 11 12 function dfs(sum, index, tmp){ 13 if(sum === target){ 14 newTmp = tmp.concat(); 15 res.push(newTmp); 16 return; //pruning 17 }else if(sum > target){ 18 return; //pruning 19 } 20 for(var i = index; i < candidates.length; i++){ 21 newTmp = tmp.concat(); 22 newTmp.push(candidates[i]); 23 dfs(sum + candidates[i], i, newTmp); 24 } 25 } 26 function sorting(a, b){ 27 if(a > b){ 28 return 1; 29 }else if(a < b){ 30 return -1; 31 }else{ 32 return 0; 33 } 34 } 35 };