OJ 组合总和

题目:

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例:

代码编程:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> ans;
    vector<int> path;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        dfs(candidates, 0, target);
        return ans;
    }

    void dfs(vector<int>& cs, int deep, int target) {
        if (target == 0) {
            ans.push_back(path); // 搜到一种答案
            return;
        }
        if (deep == cs.size()) {
            // 深度等于可选数组 则该dfs组合不对 必须在if(target ==
            // 0)前面,不然可能导致最后一个元素 == target的时候选不上
            return;
        }
        for (int i = 0; i * cs[deep] <= target; i++) {
            // 按照从左向右每个数字的个数枚举
            //这是一个循环,用于尝试当前深度的数字cs[deep]的不同倍数,
            //直到这个数字的倍数超过目标值target。

            dfs(cs, deep + 1, target - cs[deep] * i);

            //递归调用dfs函数,尝试在当前路径上添加cs[deep]的i倍,
            //并更新目标值为target - cs[deep] * i。

            path.push_back(cs[deep]);//将当前数字cs[deep]添加到路径path中。
        }
        for (int i = 0; i * cs[deep] <= target; i++) {
            //这个循环与上面的循环相同,用于回溯,移除之前添加到路径中的数字。
            // 回溯
            path.pop_back();//从路径path中移除最后一个元素,实现回溯。
        }
    }
};

代码分析:

  1. dfs(candidates , 0 , target); 调用dfs函数开始深度优先搜索。

  2. return ans; 返回存储所有组合的二维向量。

  3. void dfs(vector<int> &cs , int deep , int target){ 定义了一个名为dfs的成员函数,用于执行深度优先搜索。它接受当前的候选数组cs、当前搜索的深度deep和当前的目标值target作为参数。

  4. if(target == 0){ 如果当前的目标值target为0,说明找到了一个有效的组合。

  5. ans.push_back(path); 将当前路径path添加到答案数组ans中。

  6. return; 返回,结束当前的递归调用。

  7. if(deep == cs.size()){ 如果当前搜索的深度等于候选数组的大小,说明已经考虑了所有候选数字,但还没有达到目标值,因此这是一个无效的路径。

  8. return; 返回,结束当前的递归调用。

  9. for(int i = 0; i * cs[deep] <= target; i++){ 这是一个循环,用于尝试当前深度的数字cs[deep]的不同倍数,直到这个数字的倍数超过目标值target

  10. dfs(cs , deep + 1 , target - cs[deep] * i); 递归调用dfs函数,尝试在当前路径上添加cs[deep]i倍,并更新目标值为target - cs[deep] * i

  11. path.push_back(cs[deep]); 将当前数字cs[deep]添加到路径path中。

  12. for(int i = 0; i * cs[deep] <= target; i++){ 这个循环与上面的循环相同,用于回溯,移除之前添加到路径中的数字。

  13. path.pop_back(); 从路径path中移除最后一个元素,实现回溯。

这段代码中的两个for循环是对称的,第一个循环用于尝试添加当前数字的不同倍数到路径中,第二个循环用于回溯,移除之前添加的数字,以便尝试其他可能的组合。这种回溯策略是解决组合问题常用的方法。

代码示意图分析:以示例一为例

题目来源:39. 组合总和 - 力扣(LeetCode)

相关推荐
lhldsg5 小时前
课程排课系统实战指南:从数据库设计到算法调优全流程解析
java·数据库·算法·小程序
BSD_HY5 小时前
薄膜开关矩阵扫描电路设计中的防鬼键措施
人工智能·算法·矩阵·人机交互·薄膜开关·源头工厂·深圳工厂
linux-hzh5 小时前
百日算法修炼 · Day 17
数据结构·算法
XUEYUAN52125 小时前
代理日志分析与监控:代理池健康状态巡检与分级告警体系搭建(运维实战)
运维·网络·网络协议·tcp/ip·算法·架构
sel_95 小时前
【多轮对话论文导读(七)】多轮对话论文阅读笔记:从数据生成、用户模拟到上下文重构与长期记忆
论文阅读·人工智能·笔记·深度学习·算法·语言模型·自然语言处理
远游客07135 小时前
为什么用「年×100+月」做比较
算法·gin
leavesleo6 小时前
DeepSeek 偷偷给你取外号?拆一下 AI 人格化背后的技术
算法
liliangcsdn6 小时前
skewness收益偏度取负因子背后逻辑的探索
人工智能·算法·机器学习
鹿角片ljp6 小时前
LeetCode 300. 最长递增子序列|从 DP O (n²) 到贪心 + 二分 O (n log n)
算法·动态规划
叠层归一研究院6 小时前
缝合维度:时空3+1结构的拓扑起源
人工智能·算法·机器学习·agi