ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

回溯算法练习——4、组合总和II(C++和Python描述)

2021-09-09 22:05:27  阅读:201  来源: 互联网

标签:target Python res C++ II int startIndex candidates path


本题的力扣链接:https://leetcode-cn.com/problems/combination-sum-ii/

目录

1、题目描述:

在这里插入图片描述
在这里插入图片描述

2、思路:

在这里插入图片描述
在这里插入图片描述

其实看完上面的话,还是很迷,因此,这里再解释下:(来源

这个避免重复当思想是在是太重要了。
这个方法最重要的作用是,可以让同一层级,不出现相同的元素。即
例1:
                  1
                 / \
                2   2  这种情况不会发生 但是却允许了不同层级之间的重复即:
               /     \
              5       5
例2:
                  1
                 /
                2      这种情况确是允许的
               /
              2  
                
为何会有这种神奇的效果呢?

首先 i-1 == i 是用于判定当前元素是否和之前元素相同的语句。这个语句就能砍掉例1。
可是问题来了,如果把所有当前与之前一个元素相同的都砍掉,那么例二的情况也会消失。 
因为当第二个2出现的时候,他就和前一个2相同了。
                
那么如何保留例2呢?
那么就用i > startIndex 来避免这种情况,你发现例1中的两个2是处在同一个层级上的,
例2的两个2是处在不同层级上的。
在一个for循环中,所有被遍历到的数都是属于一个层级的。我们要让一个层级中,
必须出现且只出现一个2,那么就放过第一个出现重复的2,但不放过后面出现的2。
第一个出现的2的特点就是 i == startIndex,第二个出现的2 特点是i > startIndex

3、代码:

3.1 python代码:

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        res = [] # 保存从根到树叶路径上收集到元素的集合
        path = [] # 保存路径上符合条件的元素
        def backtracking(startIndex, s):
            if s == target:
                res.append(path.copy())
                return
            for i in range(startIndex, len(candidates)):
                if s + candidates[i] > target:
                    break
                if i > startIndex and candidates[i] == candidates[i-1]: # 这一步解题的关键,我上面专门有解释的
                    continue
                # 1.累计和,并收集路径上的元素
                s += candidates[i]
                path.append(candidates[i])
                # 2.递归,也就是下一层
                backtracking(i+1, s) # i+1表示当前元素不重复
                # 3.回溯,撤销操作
                s -= candidates[i]
                path.pop()
        candidates.sort() # 从小到大排序才能剪枝
        backtracking(0, 0)
        return res        

在这里插入图片描述

3.2 C++代码:

class Solution {
private:
    vector<vector<int>> res;
    vector<int> path;
    void backtracking(vector<int>& candidates, int target, int startIndex, int s){
        if(s == target){
            res.push_back(path);
            return;
        }
        for(int i = startIndex; i < candidates.size(); i++){
            if(s + candidates[i] > target){
                break;
            }
            // 下面这一步是这个题的精华,解释在前面
            if(i > startIndex && candidates[i-1] == candidates[i]){ // 这里数组不越界,是因为i是从startIndex开始遍历的
                continue;
            }
            // 1.累计和,并收集路径上的元素
            s += candidates[i];
            path.push_back(candidates[i]);
            // 2.递归,也就是下一层
            backtracking(candidates, target, i+1, s); // i+1表示当前元素不重复
            // 3.回溯,即撤销操作
            s -= candidates[i];
            path.pop_back();
        }
    }

public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end()); // 从小打到排序才能剪枝
        backtracking(candidates, target, 0, 0);
        return res;
    }
};

在这里插入图片描述

标签:target,Python,res,C++,II,int,startIndex,candidates,path
来源: https://blog.csdn.net/weixin_45901519/article/details/120210533

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有