No.205 - LeetCode[40] Combination Sum II - 01背包去重组合数

本文探讨了解决LeetCode第40题“组合总和II”的算法思路,对比了动态规划(DP)与贪心+深度优先搜索(DFS)两种方法。通过具体示例说明了DP方法在解决路径问题时可能遇到的重复组合数问题,并提供了贪心+DFS的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dp思路不行,会出现重复组合数,
例如
[3,1,3,5,1,1]\n8,
[4,4,2,1,4,2,2,1,3]\n6,

这种要求路径的问题,先考虑贪心+dfs了。

WA的dp代码:

/*
 * @lc app=leetcode id=40 lang=cpp
 *
 * [40] Combination Sum II
 */

// @lc code=start
class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        int N = candidates.size();
        sort(candidates.begin(),candidates.end());

        vector<vector<int>> V(target+1);

        vector<int> dp(target+1,0);
        dp[0] = 1;
        for(int i=0;i<N;i++){
            if(candidates[i] > target) break;
            for(int j=target-candidates[i];j>=0;j--){
                if(dp[j] > 0){
                    int next = j+candidates[i];
                    dp[next] += dp[j];
                    int l = V[next].size();
                    if(l == 0 || (l > 0 && V[next][l-1] != j)){
                        V[next].push_back(j);
                    }
                }
            }
        }
/*
        for(int i=0;i<=target;i++){
            printf("%d : ",i);
            for(int j=0;j<V[i].size();j++){
                printf("%d ",V[i][j]);
            }
            printf("\n");
        }
*/
        vector<vector<int>> ans;
        vector<int> path;
        dfs(ans,V,path,target);

        return ans;
    }
    void dfs(vector<vector<int>>& ans,vector<vector<int>>& V,vector<int>& path,int level){
        if(level == 0){
            ans.push_back(path);
            return ;
        }
        for(int i=0;i<V[level].size();i++){
            int now = level - V[level][i];
            int l = path.size();
            if(l == 0 || (l > 0 && path[l-1] >= now)){
                path.push_back(now);
                dfs(ans,V,path,V[level][i]);
                path.pop_back();
            }
        }
    }
};
// @lc code=end

贪心+dfs代码:

/*
 * @lc app=leetcode id=40 lang=cpp
 *
 * [40] Combination Sum II
 */

// @lc code=start
class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        vector<vector<int>> ans;
        vector<int> path;
        dfs(ans,candidates,path,0,candidates.size(),target);
        return ans;
    }
    void dfs(vector<vector<int>>& ans,vector<int>& c,vector<int>& path,int L,int R,int K){
        if(K == 0){
            ans.push_back(path);
            return ;
        }
        if(K < 0 || L >= R) return ;
        for(int i=L;i<R;i++){
            path.push_back(c[i]);
            dfs(ans,c,path,i+1,R,K-c[i]);
            path.pop_back();
            while(i+1<R && c[i+1] == c[i]) i++;
        }
    }
};
// @lc code=end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值