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, a1a2 ≤ … ≤ 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]

 

这个题是一个NP问题,方法仍然是N-Queens中介绍的套路。基本思路是先排好序,然后每次递归中把剩下的元素一一加到结果集合中,并且把目标减去加入的元素,然后把剩下元素(包括当前加入的元素)放到下一层递归中解决子问题。算法复杂度因为是NP问题,所以自然是指数量级的。代码如下: 

 

  1. public ArrayList<ArrayList<Integer>> combinationSum(int[] candidates, int target) {  
  2.     ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();  
  3.     if(candidates == null || candidates.length==0)  
  4.         return res;  
  5.     Arrays.sort(candidates);  
  6.     helper(candidates,0,target,new ArrayList<Integer>(),res);  
  7.     return res;  
  8. }  
  9. private void helper(int[] candidates, int start, int target, ArrayList<Integer> item,   
  10. ArrayList<ArrayList<Integer>> res)  
  11. {  
  12.     if(target<0)  
  13.         return;  
  14.     if(target==0)  
  15.     {  
  16.         res.add(new ArrayList<Integer>(item));  
  17.         return;  
  18.     }  
  19.     for(int i=start;i<candidates.length;i++)  
  20.     {  
  21.         if(i>0 && candidates[i]==candidates[i-1])  
  22.             continue;  
  23.         item.add(candidates[i]);  
  24.         helper(candidates,i,target-candidates[i],item,res);  
  25.         item.remove(item.size()-1);  
  26.     }  
  27. }  

注意在实现中for循环中第一步有一个判断,那个是为了去除重复元素产生重复结果的影响,因为在这里每个数可以重复使用,所以重复的元素也就没有作用了,所以应该跳过那层递归。这道题有一个非常类似的题目Combination Sum II,有兴趣的朋友可以看看,一次搞定两个题哈。

 

 

class Solution {
private:
    void combineHelper(vector<int> &candidates, int start, int sum, int target, vector<int> &answer, 
        vector<vector<int> > &result) {
        
        if (sum == target) {
            result.push_back(answer);
            return;
        }
        if (start == candidates.size() || candidates[start] + sum > target) {
            return;
        }
        
        answer.push_back(candidates[start]);
        combineHelper(candidates, start, sum+candidates[start], target, answer, result);
        answer.pop_back();
        
        combineHelper(candidates, start+1, sum, target, answer, result);
    }

public:
    vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
        /* https://oj.leetcode.com/problems/combination-sum/
        * The same repeated number may be chosen from candidates unlimited number of times.
        * 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).
        */
        
        vector<vector<int> > result;
        vector<int> answer;
        sort(candidates.begin(), candidates.end());
        
        combineHelper(candidates, 0, 0, target, answer, result);
        
        return result;
    }
};

 

 

//This is just like a coin change/knapsack problem. We need to create a vector of the size of target. //and for each o(1)...o(target) we get the values. and if in between we find any sum == target, //add that into the result

class Solution {
public:
    vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
        vector< vector< vector<int> > > combinations(target + 1, vector<vector<int>>());
        combinations[0].push_back(vector<int>());
        for (auto& score : candidates)
            for (int j = score; j <= target; j++)
                if (combinations[j - score].size() > 0) {
                    auto tmp = combinations[j - score];
                    for (auto& s : tmp)
                        s.push_back(score);
                    combinations[j].insert(combinations[j].end(), tmp.begin(), tmp.end());
                }
        auto ret = combinations[target];
        for (int i = 0; i < ret.size(); i++)
            sort(ret[i].begin(), ret[i].end());
        return ret;
    }
};

 

class Solution {
public:
    vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector< vector< vector<int> > > combinations(target + 1, vector<vector<int>>());
        combinations[0].push_back(vector<int>());
        for (auto& score : candidates)
            for (int j = score; j <= target; j++){
                auto sls = combinations[j - score];
                if (sls.size() > 0) {
                    for (auto& s : sls)
                        s.push_back(score);
                    combinations[j].insert(combinations[j].end(), sls.begin(), sls.end());
                }
            }
        return combinations[target];
    }
};

 

posted on 2015-01-11 08:56  风云逸  阅读(96)  评论(0)    收藏  举报