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];
    }
}

tiffanytown
6 声望2 粉丝

keep learning