LeetCode题解:Combination Sum I and II

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, 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]

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.
  • 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 10,1,2,7,6,1,5 and target 8,
A solution set is:
[1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]

思路:

通过递归来构造排列组合。

其实另一个思路是构造一个特定的进制数。对于第一个问题,可以用二进制来表示,第i个bit为1的时候表示使用这个数,反之表示不使用这个数。然后进行一次循环。第二个问题可以按照每个数字出现的次数来规定进位制度。缺点是可能会进行额外的大量计算,而且会更复杂。

题解:

class Solution {
public:
    vector<vector<int>> result;
    vector<int> hist;
    vector<int> cc;
    
    void generate_combinations(size_t index, int target)
    {
        if (target == 0)
        {
            result.push_back(hist);
            return;
        }
        
        if (index == cc.size())
            return;
        
        int usage = 0;
        while(target >= 0)
        {
            generate_combinations(index + 1, target);
            
            ++usage;
            target -= cc[index];
            hist.push_back(cc[index]);
        }
        
        for(int i = 0; i < usage; ++i)
            hist.pop_back();
    }
    
    vector<vector<int> > combinationSum(vector<int> &candidates, int target) {
        cc.swap(candidates);
        sort(begin(cc), end(cc));
        result.clear();
        hist.clear();
        
        if (cc.empty())
            return result;
        
        generate_combinations(0, target);
        return result;
    }
};

class Solution
{
public:
    vector<int> cc;
    vector<pair<int, int>> cc_count;
    vector<vector<int>> result;
    vector<int> history;
    
    void generate_combination (size_t index, int target)
    {
        if (target < 0)
            return;
            
        if (target == 0)
        {
            result.push_back (history);
            return;
        }
        
        if (index == cc_count.size())
            return;
            
        int i;
        for (i = 0; i <= cc_count[index].second; ++i)
        {
            generate_combination (index + 1, target);
            target -= cc_count[index].first;
            if (target < 0)
                break;
                
            history.push_back (cc_count[index].first);
        }
        
        for (int j = 0; j < i; ++j)
            history.pop_back();
    }
    
    vector<vector<int> > combinationSum2 (vector<int>& num, int target)
    {
        result.clear();
        cc_count.clear();
        
        cc.swap (num);
        sort (begin (cc), end (cc));
        
        while (!cc.empty() && cc.back() > target) cc.pop_back();
        
        if (cc.empty())
            return result;
            
        int val = cc.front(), count = 1;
        for (size_t i = 1; i < cc.size(); ++i)
        {
            if (cc[i] == val)
                ++count;
            else
            {
                cc_count.push_back (make_pair (val, count));
                val = cc[i], count = 1;
            }
        }
        cc_count.push_back (make_pair (val, count));
        
        generate_combination (0, target);
        
        return result;
    }
};


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值