LeetCode 40. 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.
  • 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]
]

本来这一题用的还是上一题的方法,还超级麻烦,结果时间复杂度很高。
代码如下:

class Solution
{

    void dfs(vector<vector<int>>&ans, int target, unordered_map<int, int> &mp, unordered_map<int, int> mk, vector<vector<int>> &vec, vector<int> res)
    {
        for(auto &i : vec[target])
        {
            if(mk[target-i]+1 > mp[target-i])
                continue;

            res.push_back(target - i);
            mk[target-i] ++;

            if(i != 0)
                dfs(ans, i, mp, mk, vec, res);
            else
                ans.push_back(res);
            res.pop_back();
            mk[target-i] --;
        }
    }

public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
    {
        sort(candidates.begin(), candidates.end());

        vector<bool> dp(target+1, false);
        dp[0] = true;

        vector<vector<int>> vec(target+1);
        unordered_map<int, int> mp;
        for(int i=0; i < candidates.size(); ++ i)
        {
            mp[candidates[i]] ++;
            for(int j=target; j>=candidates[i]; --j)
            {
                if(dp[j-candidates[i]])
                {
                    dp[j] = true;
                    vec[j].push_back(j-candidates[i]);
                }
            }
        }
        vector<vector<int>>ans;
        dfs(ans, target, mp, unordered_map<int, int>{},  vec, vector<int>{});

        if(ans.size() <= 1)
            return ans;

        for(auto &i : ans)
            sort(i.begin(), i.end());

        for(int i=0; i<ans.size(); ++ i)
        {
            for(int j=i+1; j<ans.size(); ++ j)
            {
                if(ans[i].size() > ans[j].size())
                    swap(ans[i], ans[j]);
                if(ans[i].size() == ans[j].size())
                {
                    for(int k=0; k<ans[i].size(); ++ k)
                    {
                        if(ans[i][k] > ans[j][k])
                            swap(ans[i], ans[j]);
                        if(ans[i][k] < ans[j][k])
                            break;
                    }
                }
            }
        }

        vector<vector<int>>ans1;
        ans1.push_back(ans[0]);
        for(int i=1; i<ans.size(); ++ i)
        {
            if(ans[i].size() == ans[i-1].size())
            {
                bool is = false;
                for(int j=0; j<ans[i].size(); ++ j)
                    if(ans[i][j] != ans[i-1][j])
                        is = true;
                if(is)
                    ans1.push_back(ans[i]);
            }
            else
                ans1.push_back(ans[i]);
        }
        return ans1;
    }
};

由于这一题,每一个数字只需要出现一次, 那么完全不必要这样,直接进行搜索就可以了。
参考博客:http://www.acmerblog.com/leetcode-solution-combination-sum-ii-6255.html

  • 将原数组进行排序。
  • 从小到大开始选,选择一个数后,再选取数字从后面开始选。
  • 对于同一层的数字,如果前面选取的数字等于现在选取的数字时, 那么在搜索前面的数字时,已经包含这种情况了,所以只需要跳过就好了
class Solution
{
    static void dfs(vector<int>&candidates, int target, int bg, vector<vector<int>> &vec, vector<int>&res)
    {
        if(target == 0)
        {
            vec.push_back(res);
            return;
        }
        int p = -1;
        for(int i=bg; i<candidates.size(); ++ i)
        {
            if(candidates[i] > target)
                return;
            if(candidates[i] == p)
                continue;
            p = candidates[i];
            res.push_back(candidates[i]);
            dfs(candidates, target-candidates[i], i+1, vec, res);
            res.pop_back();
        }
    }
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
    {
        sort(candidates.begin(), candidates.end());
        vector<vector<int>> vec;
        vector<int> res;
        dfs(candidates, target, 0, vec,  res);
        return vec;
    }
};

原文地址:https://www.cnblogs.com/aiterator/p/6614045.html