• 力扣--深度优先算法/回溯算法40.组合总和 Ⅱ


    这题和组合总和Ⅰ的区别在于两点:
    1.同一个数不能重复选;
    2.数组中可能可以有重复的数这样会导致重复选。

    例如[1,2,1],target为3时,[[1,2],[2,1]],但是这样两个算是同一组和,而如果用set把重复的去了,又会导致当target为2时,只有[2],而[1,1]这个答案就忽略了。

    那么该怎么办?

    思路分析:

    1. 深度优先搜索 (DFS): 通过递归实现,尝试从给定的数字集合 candidates 中选择可能的数字,构建和为 target 的组合。
    2. 递归函数 dfs
      • 接收参数:candidates 为数字集合,target 为目标和,start 为当前选择的数字起始位置,nownum 为当前组合的和。
      • 遍历当前可能的数字,如果当前数字加上当前组合的和已经超过目标值 target,则跳过当前数字。
      • 避免重复选择相同的数字,如果当前数字与前一个数字相同且不是起始位置,则跳过。
      • 将当前数字加入临时结果集 path,更新当前组合的和 nownum
      • 如果当前组合的和等于目标值 target,将临时结果集加入最终结果集 result
      • 否则,继续递归生成组合,注意起始位置更新为 i+1
      • 回溯过程中,撤销选择,继续尝试其他可能的组合。
    3. 主函数:
      • 对候选数组进行排序,以确保相同的数字放在一起,方便后续处理。
      • 调用深度优先搜索函数 dfs,从起始位置 0 和当前和 0 开始生成组合。
      • 返回最终结果。
    1. class Solution {
    2. // 存储最终结果的二维数组
    3. vectorint>> result;
    4. // 存储当前正在生成的组合的临时结果
    5. vector<int> path;
    6. // 定义深度优先搜索函数,用于生成组合
    7. void dfs(vector<int>& candidates, int target, int start, int nownum) {
    8. // 遍历当前可能的数字
    9. for (int i = start; i < candidates.size(); i++) {
    10. // 如果当前数字加上当前组合的和已经超过目标值 target,则跳过当前数字
    11. if (candidates[i] + nownum > target)
    12. break;
    13. // 避免重复选择相同的数字,如果当前数字与前一个数字相同且不是起始位置,则跳过
    14. if (i > start && candidates[i] == candidates[i - 1])
    15. continue;
    16. // 将当前数字加入临时结果集 path
    17. path.push_back(candidates[i]);
    18. nownum += candidates[i];
    19. // 如果当前组合的和等于目标值 target,将临时结果集加入最终结果集 result
    20. if (nownum == target)
    21. result.push_back(path);
    22. else
    23. // 继续递归生成组合,注意起始位置更新为 i+1
    24. dfs(candidates, target, i + 1, nownum);
    25. // 回溯,撤销选择,继续尝试其他可能的组合
    26. nownum -= candidates[i];
    27. path.pop_back();
    28. }
    29. return;
    30. }
    31. public:
    32. // 主函数,生成和为 target 的所有组合,允许重复选择相同的数字
    33. vectorint>> combinationSum2(vector<int>& candidates, int target) {
    34. // 对候选数组进行排序,方便后续处理
    35. sort(candidates.begin(), candidates.end());
    36. // 调用深度优先搜索函数 dfs,从起始位置 0 和当前和 0 开始生成组合
    37. dfs(candidates, target, 0, 0);
    38. // 返回最终结果
    39. return result;
    40. }
    41. };

    关键在于这两步:

    // 对候选数组进行排序,方便后续处理 sort(candidates.begin(), candidates.end());

    // 避免重复选择相同的数字,如果当前数字与前一个数字相同且不是起始位置,则跳过
                if (i > start && candidates[i] == candidates[i - 1])
                    continue;

    听懂掌声

  • 相关阅读:
    阿里云安全组 设置数据库仅自己电脑IP可登陆
    解析java中线程的生命周期
    BP神经网络简单应用实例,BP神经网络训练函数
    Android——m3u8视频文件下载
    Spring 对 Junit4,Junit5 的支持上的运用
    node.js学习之模块化、npm
    Unity中Shader的XRay透视效果
    【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
    游戏思考14:对cache_server缓冲服务器的问题思考(读云峰博客有感)
    什么是算子?
  • 原文地址:https://blog.csdn.net/weixin_73865269/article/details/136604680