Leetcode 40组合总和|| 题解

题目链接

题目大意

输出在一个数组中选出几个数组成一个整数的不重复具体方案
在这里插入图片描述
在这里插入图片描述

最初思路

观察到目标数字最大不超过30,且原数组中最小数为1,故一个合法方案至多不超过30个数。可以排序后使用爆搜剪枝,由于需要不重复的方案用set维护。

class Solution {
public:
    int n;
    vector<vector<int>>res;
    set<vector<int>>s;
    void dfs(int step,int t,vector<int>temp,vector<int>c)
    {    
        //cout<<t<<endl;
        if(t==0)
        {   
            //cout<<t<<endl;
            // for(auto i:temp)cout<<i<<" ";
            // cout<<endl; 
           s.insert(temp);
            return ;
        }
        if(step==n)return ;
        dfs(step+1,t,temp,c);
        if(t-c[step]>=0)
        {    
            temp.push_back(c[step]);
            dfs(step+1,t-c[step],temp,c);
        }
        
    }
    vector<vector<int>> combinationSum2(vector<int>& c, int t) {
       n=c.size();
       vector<int>temp;
       
       sort(c.begin(),c.end());
       dfs(0,t,temp,c);
       for(auto i:s)res.push_back(i);
       return res;
    }
};

这个思路没有考虑到有多个1的情况如:

[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
30
所以会导致超时,发现仅有一种方案,但是会被重复计数。这启发我们,在搜索时可以只考虑数字的大小与数量,每次处理一种数字,即先预处理出每个数字出现的次数,然后在搜索时,每次考虑用几个这个数。最终的方案形如{1个1,2个3…}

class Solution {
public:
    int n;
     vector<vector<int>>res;
     map<int,int>mp;
     vector<pair<int,int>>v;
     vector<int>temp;
    void dfs(int step,int t)
    {    
        //cout<<t<<endl;
        if(t==0)
        {   
           res.push_back(temp);
           return ;
        }
        if(step==n)return ;
        dfs(step+1,t);
        for(int i=1;i<=v[step].second;i++)
       { 
           if(t-i*v[step].first>=0)
           { 
             for(int j=1;j<=i;j++)temp.push_back(v[step].first);
             dfs(step+1,t-i*v[step].first);
             for(int j=1;j<=i;j++)temp.pop_back();
           }
       }
    }
     vector<vector<int>> combinationSum2(vector<int>& c, int t) {
      
       vector<int>temp;
       sort(c.begin(),c.end());
       for(int i=0;i<c.size();i++)
       {
           mp[c[i]]++;
       }
       n=mp.size();
       for(auto i:mp)v.push_back({i.first,i.second});
       //for(auto i:v)cout<<i.first<<" "<<i.second<<endl;
       dfs(0,t);
       return res;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值