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)