代码随想录算法训练营第二十七天 | 39. 组合总和 、40.组合总和II、131.分割回文串

题目链接:leetcode 39. 组合总和

文章讲解:代码随想录 39. 组合总和讲解

视频讲解:Leetcode:39. 组合总和讲解

思路和解法

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

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

对于给定的输入,保证和为 target 的不同组合数少于 150 个。
想法:
给的数组无重复元素,每个元素可以任意使用,递归时就不要从下一个数字开始尝试,而是从当前数字继续开始尝试加进去。如果要剪枝一定要先排序,只有排序才能认为当前数字加进来已经超过target,后面就不用再遍历了。

class Solution {
public:
    //存结果与路径
    vector<vector<int>> result;
    vector<int> path;
    //递归+回溯
    void backTracking(vector<int>& candidates, int target, int startIndex, int sum) {
        //终止条件
        if (sum > target) {
            return ;
        }
        if (sum == target) {
            result.push_back(path);
            return ;
        }
        //递归处理逻辑
        //横向遍历
        //这里还可以做剪枝 剪枝需要先排序
        // for (int i = startIndex; i < candidates.size(); i++) {
        for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {
            sum += candidates[i];
            path.push_back(candidates[i]);
            backTracking(candidates, target, i, sum);
            path.pop_back();
            sum -= candidates[i];
        }
        return ;
    }

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        //初始化
        result.clear();
        path.clear();
        //剪枝需要先排序
        sort(candidates.begin(), candidates.end());
        //递归回溯
        backTracking(candidates, target, 0, 0);
        return result;
    }
};

题目链接:leetcode 40.组合总和II

文章讲解:代码随想录 40.组合总和II讲解

视频讲解:回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II

思路和解法

题目:
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。
想法:
给的数组有重复元素,每个元素只能用一次,所以递归时要从下一个数字开始尝试加入,另外一定要先排序,因为要去重,排序以后才方便去重,去重的逻辑是:比如[1,1,1,2,3],第一个选1以后,第二个可以选第二个1,也可以选第3个1,但是假如target=4,这样导致递归到[1,1,2]可能是第一个1和第二个1,也可能是第一个1和第三个1,所以递归时再选择第二个数字时要跳过第三个1这种情况,就判断当前层for循环遍历到的数字和前一个数字是否相同,相同跳过。注意第二个1在第二层不用跳过。

class Solution {
public:
    //组合问题一定要这两个
    vector<vector<int>> result;
    vector<int> path;
    //回溯+递归
    void backTracking(const vector<int>& candidates, const int target, int sum, int startIndex) {
        //终止条件
        if (sum == target) {
            result.push_back(path);
            return ;
        }
        if (sum > target) {
            return ;
        }
        //递归处理逻辑
        for (int i = startIndex; i < candidates.size(); i++) {
            if (i > startIndex && candidates[i] == candidates[i - 1]) {
                continue;
            }
            sum += candidates[i];
            path.push_back(candidates[i]);
            backTracking(candidates, target, sum, i + 1);
            path.pop_back();
            sum -= candidates[i];
        }
        return ;
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        result.clear();
        path.clear();
        sort(candidates.begin(), candidates.end());
        backTracking(candidates, target, 0, 0);
        return result;
    }
};

题目链接:leetcode 131.分割回文串

文章讲解:代码随想录 131.分割回文串讲解

视频讲解:131.分割回文串

思路和解法

题目:
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

回文串 是正着读和反着读都一样的字符串。
想法:
分割线类似选数字,要提前规定好分割线的意义,本次使用的就是[startIndex, i]这样的左闭右闭区间,这道题目的终止条件就是分割线把整个字符串全部割完了同时每个子串都满足回文。回文串判断用双指针。

class Solution {
public:
    //回溯+递归
    vector<string> path;
    vector<vector<string>> result;
    //判断是否为回文串
    bool isValid(string& s) {
        for (int i = 0, j = s.size() - 1; i < j; i++, j--) {
            if (s[i] != s[j]) return false;
        }
        return true;
    }

    void backTracking(const string& s, int startIndex) {
        //终止条件 截取的子串为[startIndex, i] 所以startIndex超过字符串长度为终止条件
        if (startIndex >= s.size()) {
            result.push_back(path);
            return ;
        }
        //递归处理逻辑 截取的子串为[startIndex, i],判断截取出来的子串是否为回文串,如果是继续向后分割,如果不是跳过当前分割
        for (int i = startIndex; i < s.size(); i++) {
            //substr(起始下标,长度)
            string tempString = s.substr(startIndex, i - startIndex + 1);
            //判断是否为回文串
            if (isValid(tempString)) {
                path.push_back(tempString);
                backTracking(s, i + 1);
                path.pop_back();
            } else {
                continue;
            }
        }
        return ;
    }
    vector<vector<string>> partition(string s) {
        path.clear();
        result.clear();
        backTracking(s, 0);
        return result;
    }
};
  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值