zoukankan      html  css  js  c++  java
  • 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;
        }
    };
    
    
  • 相关阅读:
    Android 手机摇一摇功能的实现
    Android 只开启一个Activity实例
    android 获取Datepicker日期
    帧动画
    进度条ProgressDialog
    AlertDialog错误
    ListView加checkBox可以实现全选等功能
    一些自己常用的工具类
    错层
    Parallax
  • 原文地址:https://www.cnblogs.com/aiterator/p/6614045.html
Copyright © 2011-2022 走看看