LeetCode 39/40. Combination Sum i, ii

Posted 枯萎的海风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 39/40. Combination Sum i, ii相关的知识,希望对你有一定的参考价值。

1. 题目描述

39

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

40

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

2. 解题思路

使用回溯的算法思想, 对于含有重复元素的, 可以在最后进行排序, 去除重复元素实现需求

3. code

3.1 39

class Solution 
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) 
        sort(candidates.begin(), candidates.end());
        vector<vector<int>> res;
        vector<int> tmp;
        helper(res, tmp, candidates, target, 0);
        return res;
    

private:
    void helper(vector<vector<int>> & res, vector<int> & cur_set, const vector<int>& candidates, int target, int depth)
        if (target == 0)
            res.push_back(cur_set);
            return;
        

        if (target < 0 || depth == candidates.size())
            return;

        helper(res, cur_set, candidates, target, depth + 1);
        cur_set.push_back(candidates[depth]);
        helper(res, cur_set, candidates, target - candidates[depth], depth);
        cur_set.pop_back();
    
;

3.2 40

class Solution 
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) 
        sort(candidates.begin(), candidates.end());
        vector<vector<int>> res;
        vector<int> tmp;
        helper(res, tmp, candidates, target, 0);
        sort(res.begin(), res.end());
        res.erase(unique(res.begin(), res.end()), res.end());
        return res;
    

private:
    void helper(vector<vector<int>> & res, vector<int> & cur_set, const vector<int>& candidates, int target, int depth)
        if (target == 0)
            res.push_back(cur_set);
            return;
        

        if (target < 0 || depth >= candidates.size())
            return;

        helper(res, cur_set, candidates, target, depth + 1);
        cur_set.push_back(candidates[depth]);
        helper(res, cur_set, candidates, target - candidates[depth], depth + 1);
        cur_set.pop_back();
    
;

4. 大神解法

这段检测重复元素的代码是核心

if(i&&num[i]==num[i-1]&&i>order) continue; // check duplicate combination
/*
At the beginning, I stuck on this problem. After careful thought, I think this kind of backtracking contains a iterative component and a resursive component so I'd like to give more details to help beginners save time. The revursive component tries the elements after the current one and also tries duplicate elements. So we can get correct answer for cases like [1 1] 2. The iterative component checks duplicate combinations and skip it if it is. So we can get correct answer for cases like [1 1 1] 2.
*/
class Solution 
public:
    vector<vector<int> > combinationSum2(vector<int> &num, int target) 
    
        vector<vector<int>> res;
        sort(num.begin(),num.end());
        vector<int> local;
        findCombination(res, 0, target, local, num);
        return res;
    
    void findCombination(vector<vector<int>>& res, const int order, const int target, vector<int>& local, const vector<int>& num)
    
        if(target==0)
        
            res.push_back(local);
            return;
        
        else
        
            for(int i = order;i<num.size();i++) // iterative component
            
                if(num[i]>target) return;
                if(i&&num[i]==num[i-1]&&i>order) continue; // check duplicate combination
                local.push_back(num[i]),
                findCombination(res,i+1,target-num[i],local,num); // recursive componenet
                local.pop_back();
            
        
    
;

以上是关于LeetCode 39/40. Combination Sum i, ii的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode39/40/22/77/17/401/78/51/46/47/79 11道 Backtracking

力扣-39(40)-组合总和I(II)

如何在java中单击按钮时检测修饰键组合

Day39~40-进程线程

thinkphp 循环数组

php数组求和函数