Leetcode: Combination Sum
2017-07-30 22:24
357 查看
已知数组C和目标值T,要求在C中找出所有独特的组合使其和为T,C中所有的数和T都为正整数
1. C中无重复
2. 同一个数在组合中可以出现任意次
比如C=[2, 3, 6, 7] ,T=7, 解为
简单回溯 + 排序优化
1. C中可能有重复值
2. C中的每一个数在组合中只能出现一次
如C = [10, 1, 2, 7, 6, 1, 5], T = 8, 解为
Note:
1. C中无重复
2. C中的每一个数在组合中可出现任意次
如C = [1, 2, 3], T = 4, 则
递归,会超时,因为存在的大量重复计算(调用)
动态规划(从dp[0]到dp[target]都要计算,其中大部分可能都是不必要的)
动态规划+递归(可以将dp[]看作缓存),避免了重复计算和不必要的计算
39. Combination Sum
Note:1. C中无重复
2. 同一个数在组合中可以出现任意次
比如C=[2, 3, 6, 7] ,T=7, 解为
[ [7], [2, 2, 3] ]
解法
简单回溯public class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> result = new ArrayList<>(); findCombination(result, new ArrayList<Integer>(), candidates, target, 0); return result; } public void findCombination(List<List<Integer>> result, List<Integer> combinations, int[] candidates, int remain, int start){ if(remain < 0) return; if (remain == 0){ result.add(new ArrayList<Integer>(combinations)); } //每递归一层for循环确定一个位置的数,如第k层for循环就确定第k个数 for(int i = start; i < candidates.length; i++) { combinations.add(candidates[i]); findCombination(result, combinations, candidates, remain - candidates[i], i);//start置为i表明允许多次使用同一个数 combinations.remove(combinations.size()-1); } } }
简单回溯 + 排序优化
public class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> result = new ArrayList<>(); //排序优化 Arrays.sort(candidates); findCombination(result, new ArrayList<Integer>(), candidates, target, 0); return result; } public void findCombination(List<List<Integer>> result, List<Integer> combinations, int[] candidates, int remain, int start){ if(remain < 0) return; if (remain == 0){ result.add(new ArrayList<Integer>(combinations)); } //每递归一层for循环确定一个位置的数,如第k层for循环就确定第k个数 for(int i = start; i < candidates.length && candidates[i] <= remain; i++) { //当c[i]大于remain,则i以及i以后的都不会符合 combinations.add(candidates[i]); findCombination(result, combinations, candidates, remain - candidates[i], i); combinations.remove(combinations.size()-1); } } }
40. Combination Sum II
Note:1. C中可能有重复值
2. C中的每一个数在组合中只能出现一次
如C = [10, 1, 2, 7, 6, 1, 5], T = 8, 解为
[ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
解法
利用排序去重public class Solution { public List<List<Integer>> combinationSum2(int[] candidates, int target) { List<List<Integer>> result = new ArrayList<>(); Arrays.sort(candidates);//先排序以便去重 findCombination(result, new ArrayList<Integer>(), candidates, target, 0); return result; } public void findCombination(List<List<Integer>> result, List<Integer> combinations, int[] candidates, int remain, int start){ if(remain < 0) return; if (remain == 0){ result.add(new ArrayList<Integer>(combinations)); } //每层for循环确定一个位置的数,如第k层确定第k个数 for(int i = start; i < candidates.length && candidates[i] <= remain; i++) { //保证当前位置不会重复使用相等的数,如1,1,2,5,6,7,10,位置0只可能使用第一个1,位置1只可能使用第二个1 if(i > start && candidates[i] == candidates[i-1]) continue; combinations.add(candidates[i]); findCombination(result, combinations, candidates, remain - candidates[i], i + 1); combinations.remove(combinations.size()-1); } } }
377. Combination Sum IV
只需求出所有可能组合的数量Note:
1. C中无重复
2. C中的每一个数在组合中可出现任意次
如C = [1, 2, 3], T = 4, 则
可能的所有组合为 (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1) 故结果为7.
解法
递推公式:comb[target] = sum(comb[target - nums[i]]) (0 <= i < nums.length && target >= nums[i]),comb[0] = 1。递归,会超时,因为存在的大量重复计算(调用)
public class Solution { public int combinationSum4(int[] nums, int target) { if (target == 0) return 1; int res = 0; for (int i = 0; i < nums.length; i++) { if (target >= nums[i]) { res += combinationSum4(nums, target - nums[i]); } } return res; } }
动态规划(从dp[0]到dp[target]都要计算,其中大部分可能都是不必要的)
public class Solution { public int combinationSum4(int[] nums, int target) { int [] dp = new int[target + 1]; dp[0] = 1; for(int i = 1; i <= target; i++){ for(int j = 0; j < nums.length; j++){ dp[i] += (i - nums[j]) < 0 ? 0 : dp[i-nums[j]]; } } return dp[target]; } }
动态规划+递归(可以将dp[]看作缓存),避免了重复计算和不必要的计算
public class Solution { public int combinationSum4(int[] nums, int target) { int[] dp = new int[target + 1]; Arrays.fill(dp, -1); dp[0] = 1; return helper(nums, target, dp); } private int helper(int[] nums, int target, int[] dp) { //已计算过直接返回 if (dp[target] != -1) return dp[target]; int res = 0; for (int i = 0; i < nums.length; i++) { if (target >= nums[i]) { res += helper(nums, target - nums[i], dp); } } dp[target] = res; return res; } }
相关文章推荐
- [LeetCode] Combination Sum (bfs)
- Combination Sum 组合数求和-Leetcode
- *LeetCode-Combination Sum
- 从Leetcode的Combination Sum系列谈起回溯法
- Leetcode Java-Combination Sum
- leetcode Combination Sum
- [LeetCode][Java] Combination Sum
- leetcode之组合数(Combination Sum)
- leetcode:combination sum
- leetcode-Combination Sum
- LeetCode_Combination Sum
- leetcode:Combination Sum
- [Leetcode] Combination Sum (Java)
- [leetcode]Combination Sum
- LeetCode: Combination Sum
- LeetCode: Combination Sum [038]
- Leetcode 39 Combination Sum
- [leetcode 39] Combination Sum
- LeetCode Online Judge 题目C# 练习 - Combination Sum
- 算法。递归。之一: combination sum, leetcode