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.
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]
]
1.解题思路
对数组进行排序,每次加入第i个数后,target就减去这个数,并作为新的target,进行递归。如果target<0,则说明本次无解;如果target=0,则将本序列组合加入结果集中。因为数字可以repeated,所以每次递归都从第i个开始。
2.代码
public class Solution {
List<List<Integer>> res=new ArrayList<List<Integer>>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
if(candidates.length==0) return res;
Arrays.sort(candidates);
combine(candidates,target,0,new ArrayList<Integer>());
return res;
}
private void combine(int[] candidates, int target, int index,List<Integer> pre){
if(target<0) return;
if(target==0){
res.add(pre);
return;
}
for(int i=index;i<candidates.length;i++){
List<Integer> cur=new ArrayList<Integer>(pre);
cur.add(candidates[i]);
combine(candidates,target-candidates[i],i,cur);
}
}
}
Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
1.解题思路
本题与上一题的区别就是同一个数字在一个组合中只能出现一次,那么就需要考虑下面两种情况:
1) 每次递归开始的index要加1;
2)在同一个for循环中,即针对同一个target,需要排除重复的数字。因为数组已经事先进行排序,所以只要判断下当前数字是否和前一个数字相等即可。
2.代码
public class Solution {
List<List<Integer>> res=new ArrayList<List<Integer>>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if(candidates.length==0) return res;
Arrays.sort(candidates);
combineHelper(candidates,0,target,new ArrayList<Integer>());
return res;
}
private void combineHelper(int[] candidates,int index,int target,List<Integer> pre){
if(target<0) return;
if(target==0){
res.add(pre);
return;
}
for(int i=index;i<candidates.length;i++){
if(i>index&&candidates[i]==candidates[i-1]) continue;
List<Integer> cur=new ArrayList<Integer>(pre);
cur.add(candidates[i]);
combineHelper(candidates,i+1,target-candidates[i],cur);
}
}
}
Combination Sum III
Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
Example 1:
Input: k = 3, n = 7
Output:
[[1,2,4]]
Example 2:
Input: k = 3, n = 9
Output:
[[1,2,6], [1,3,5], [2,3,4]]
1.解题思路
其实本题与题I非常相似,只是加入了组合元素的个数限制k。题意其实就是从数组[1,2,...,9]中选出k个数,使得sum等于target。唯独一点与题I的区别就是这里每个数只能选一遍,所以每次递归都从i+1开始。
2.代码
public class Solution {
List<List<Integer>> res =new ArrayList<List<Integer>>();
public List<List<Integer>> combinationSum3(int k, int n) {
if(k==0||n==0) return res;
int[] nums={1,2,3,4,5,6,7,8,9};
combine(nums,0,n,k,new ArrayList<Integer>());
return res;
}
private void combine(int[] nums,int index,int target,int k,List<Integer> pre){
if(target<0) return;
if(target==0&&k==0){
res.add(pre);
return;
}
for(int i=index;i<nums.length;i++){
List<Integer> cur=new ArrayList<Integer>(pre);
cur.add(nums[i]);
combine(nums,i+1,target-nums[i],k-1,cur);
}
}
}
Combination Sum IV
Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.
Example:
nums = [1, 2, 3]
target = 4
The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
Note that different sequences are counted as different combinations.
Therefore the output is 7.
1.解题思路
受前面三题的启发,很容易就想到继续用递归进行回溯,但是发现Time Exceed Limit. 再仔细看题目,发现其实是动态规划。给定一个数组,求和为target的组合个数,那我们定义状态dp[i]表示和为i的数字组合的个数,那么状态转移就是dp[i]=dp[i-nums[0]]+dp[i-nums[1]]+...+dp[i-nums[n-1]];当然前提是i大于nums[]。
其实说到这,我们发现这其实和动态规划的经典题目CoinChange找零钱非常相似,但找零钱相对复杂一些,因为找零钱需要得到所有组合中拥有最少元素的组合的元素数量,即最少的纸币数目;但这一题只需要求出所有的组合数即可。
CoinChange可参考 https://segmentfault.com/a/11...
2.代码
public class Solution {
public int combinationSum4(int[] nums, int target) {
if(nums.length==0||target==0) return 0;
int[] dp=new int[target+1];
dp[0]=1;
for(int i=1;i<=target;i++){
for(int n:nums){
if(i>=n){
dp[i]+=dp[i-n];
}
}
}
return dp[target];
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。