leetcode #39 in cpp

The question is to find combination of numbers sum up to a target in a set. 

Solution: 

1. Note that a set contains no duplicates. 

2. the combination could be unlimited in size. Say target = 3, array = [1] then the output is [1,1,1].

There are two troubles in this question: 

1. how to find combination that sum up to a target. 

2Sum and 3Sum would just consider any combination of 2 numbers and 3 numbers  correspondingly. However in this problem, the combination is unlimited.

2. how to avoid duplicates. 

We know that if target = 4 and array = [1,3]. If we do not try to prevent duplicates, it would probably gives results as {[1,3] , [3,1]}. 

First Lets tackle the first trouble:

Since the combination is unlimited, recurrence should be a proper method. Let's look at the recurrent structure here.  

We know that if a + b + c + ...+ z = target, then  a + b  +c + ....+y = target - z. That is, if a target could be reached, then target - one element in the combination could also bereached. Another example is target = 6, array = [1,2, 3, 4, 6]. one combination = 1 + 2 + 3 = 6 We could see that 6 - 1 = 5  and 5 could also be found since 5 = 2 + 3. So the idea is:

findSum(vector<int> sum_components, int target, vector<int> candidates, vector<int> *result){
<span style="white-space:pre">	</span>if(target == 0) put sum_components into result// since target has reached 0, we successfully reached the original target
<span style="white-space:pre">	</span>if(target < 0) return//the sum of sum component has exceeded the original target. We abandon this combination
<span style="white-space:pre">	</span>for each component in candidates
<span style="white-space:pre">		</span>add component into sum_components
<span style="white-space:pre">		</span>findSum(sum_components, target - component, candidate, result)//find if target - component could be summed up
<span style="white-space:pre">	</span>end for

}
We have to solve the second problem, that is, getting rid of duplicates.

The way to get rid of duplicates is to maintain an index indicating where we start the combination. Say array = [3,4], target = 7. The result would give [3,4] and [4,3]. To avoid this, when recurrence is dealing with 4, 4 should not sum up with any number at its left. We know that each number would have its recurrence scanning through its right side. Thus if a number sums to target with a number at its left, this combination would have been catched by its left number. In the example, 3 would sum up with 4 in its recurrence. When the recurrence starts from 4 see 4 + 3 = 7, the [3,4] combination has already been catched by the recurrence from 3. 

Code: 

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        vector<int> members;
        sort(candidates.begin(), candidates.end());//make it in order.This is necessary for having no duplicates in results
        findSum(members,candidates,0, target, &res);
        return res;
    }
    void findSum(vector<int> members, vector<int> candidates,int start_ind, int target, vector<vector<int>> *res){
        if(target < 0) return;//no number can sum up to target
        if(target == 0){//have already sum up to target 
            res->push_back(members);
            return;
        }
        if(target < candidates[0]) return;//no number can sum up to target
        vector<int> temp_mem;
        for(int i = start_ind; i < candidates.size(); i ++){//start_ind is to avoid duplicate. 
<span style="white-space:pre">							</span>    //Each number try to combine with numerbs at its right side
            if(candidates[i] > target) break;//number is larger than target
            else{
                temp_mem = members;
                temp_mem.push_back(candidates[i]);//try this number.
                findSum(temp_mem,candidates,i,target - candidates[i], res);//try if some number can sum up target - candidates[i].
            }
        }
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值