• LeetCode.39. 组合总和


    LeetCode.39. 组合总和

    难度:medium

     

    Java:

    跳出的条件有两个,sum > target 和 sum == target;

    本题还需要startIndex来控制for循环的起始位置,对于组合问题,什么时候需要startIndex呢?

    举过例子,如果是一个集合来求组合的话,就需要startIndex,例如:77.组合 (opens new window)216.组合总和III (opens new window)

    如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:17.电话号码的字母组合

    未剪枝:

     

    1. class Solution {
    2. List> ans = new ArrayList>();
    3. List path = new ArrayList<>();
    4. int sum = 0;
    5. public List> combinationSum(int[] candidates, int target) {
    6. backTracking(candidates, target, 0);
    7. return ans;
    8. }
    9. // startIndex控制选取元素的范围,出现只是元素顺序不同的组合
    10. public void backTracking(int[] candidates, int target, int startIndex) {
    11. if (sum > target) {
    12. return;
    13. }
    14. if (sum == target) {
    15. ans.add(new ArrayList<>(path));
    16. return;
    17. }
    18. for (int i = startIndex; i < candidates.length; i++) {
    19. sum += candidates[i];
    20. path.add(candidates[i]);
    21. // startIndex = i,表明可以重复选取当前元素
    22. backTracking(candidates, target, i);
    23. sum -= candidates[i];
    24. path.remove(path.size() - 1);
    25. }
    26. }
    27. }

     剪枝方法:

    以及上面的版本一的代码大家可以看到,对于sum已经大于target的情况,其实是依然进入了下一层递归,只是下一层递归结束判断的时候,会判断sum > target的话就返回。

    其实如果已经知道下一层的sum会大于target,就没有必要进入下一层递归了。

    那么可以在for循环的搜索范围上做做文章了。

    对总集合排序之后,如果下一层的sum(就是本层的 sum + candidates[i])已经大于target,就可以结束本轮for循环的遍历

    1. class Solution {
    2. List> ans = new ArrayList>();
    3. List path = new ArrayList<>();
    4. int sum = 0;
    5. public List> combinationSum(int[] candidates, int target) {
    6. // 需要排序
    7. Arrays.sort(candidates);
    8. backTracking(candidates, target, 0);
    9. return ans;
    10. }
    11. // startIndex控制选取元素的范围,出现只是元素顺序不同的组合
    12. public void backTracking(int[] candidates, int target, int startIndex) {
    13. if (sum == target) {
    14. ans.add(new ArrayList<>(path));
    15. return;
    16. }
    17. for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {
    18. sum += candidates[i];
    19. path.add(candidates[i]);
    20. // startIndex = i,表明可以重复选取当前元素
    21. backTracking(candidates, target, i);
    22. sum -= candidates[i];
    23. path.remove(path.size() - 1);
    24. }
    25. }
    26. }

    复杂度分析:

    • 时间复杂度:O(S),其中 S 为所有可行解的长度之和。
    • 空间复杂度:O(n),n为递归的深度
  • 相关阅读:
    Python之数据库(MYSQL)连接
    面试官:你说说一条查询 SQL 的执行过程
    一些小知识点
    useragent怎么获取
    英语CN专刊《英语教师》简介及投稿须知
    [Linux](6)进程的概念,查看进程,创建子进程,进程状态,进程优先级
    Java基础知识面试题(2022年最新版,持续更新...)整理
    运维系列.在Docker中使用Grafana
    23种设计模式之桥接模式
    39、HumanNeRF
  • 原文地址:https://blog.csdn.net/weixin_45867071/article/details/126344360