代码编织梦想

代码随想录算法训练营

Day23代码随想录算法训练营第 23 天 |LeetCode 39. 组合总和 LeetCode 40.组合总和II LeetCode131.分割回文串



前言

2024.7.26 之前对于组合综合ii的去重讲解有误,现已修正

LeetCode39. 组合总和

讲解文档

LeetCode40.组合总和II

讲解文档

LeetCode131.分割回文串

讲解文档


一、基础

1、回溯可以看成N叉树

树的高度是递归深度,每一个树枝是一个路径(组合)
树的宽度是for循环遍历,选择不同的起点

2、去重

注意是不能出现重复的组合还是组合里不能出现重复的元素

不能出现重复组合:在选择起点时,不能选取重复的数字,因为一旦起点数字相同,选出来的组合就是相同的,所以每次for循环都要检查现在起点是否出现过

二、LeetCode 39. 组合总和

1.题目链接

LeetCode39. 组合总和

2.思路

3.题解

class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    int sum = 0;
    void select(vector<int>& candidates, int target, int start) {
        if (sum > target)
            return;
        if (sum == target) {
            res.push_back(path);
            return;
        }
        for (int i = start; i < candidates.size(); i++) {
            path.push_back(candidates[i]);
            sum += candidates[i];
            select(candidates, target, i);
            sum -= candidates[i];
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        select(candidates, target, 0);
        return res;
    }
};

三、LeetCode 40.组合总和II

1.题目链接

LeetCode 40.组合总和II

2.思路

(1)candidates先排序
(2)去重
candidates里面有重复数字,同一个组合里可以有重复的元素,但是不能有重复的组合
1)所以同一条路径,也就是同一个树枝上不用去重,不再每层递归中去重
2)同一层不能有重复的元素,在每层for循环中去重

candidates[i] == candidates[i - 1] ,也就是现在的元素与前一个元素重复时有两种情况

  • used[i - 1] == false 前一个元素没有出现在组合中,也就是和现在元素在同一层中竞争。关于前一个元素已经前面的循环讨论过了,并且同一层不能重复元素,所以当前元素跳过
  • used[i - 1] == true 前一个元素出现在组合中,在同一个树枝上,是现在元素的上层,而在一个组合里可以有重复元素,所以现在的元素可以用

3.题解

class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    vector<bool> used;
    int sum = 0;
    void select(vector<int>& candidates, int target, int start) {
        if (sum > target)
            return;
        if (sum == target) {
            res.push_back(path);
            return;
        }
        for (int i = start; i < candidates.size(); i++) {
            if (i > 0 && candidates[i] == candidates[i - 1] &&
                used[i - 1] == false)
                continue;
            path.push_back(candidates[i]);
            sum += candidates[i];
            used[i] = true;
            select(candidates, target, i + 1);
            sum -= candidates[i];
            path.pop_back();
            used[i] = false;
        }
    }
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        for (int i = 0; i < candidates.size(); i++) {
            used.push_back(false);
        }
        sort(candidates.begin(), candidates.end());
        select(candidates, target, 0);
        return res;
    }
};

四、LeetCode131.分割回文串

1.题目链接

LeetCode131.分割回文串

2.思路

主要分为两步:分割和回文串判定
(1)分割:递归
1)参数:字符串,分割子串的起点下标
2)边界:起点下标达到s.size()
3)单层递归:
① 遍历确定分割子串的终点下标(分割子串看作左闭右闭)
② 先判定子串是否为回文串
③ 如果是

  • 那么用s.substr(起点,终点)获取子串(substr参数是左闭右开)
  • 回文子串加入path(组合)
  • 递归,新起点为当前终点+1
  • 回溯

(2)双指针判断回文字符串

3.题解

class Solution {
public:
    vector<vector<string>> res;
    vector<string> path;
    bool huiwen(string s, int l, int r) {
        while (l < r) {
            if (s[l] != s[r])
                return false;
            l++;
            r--;
        }
        return true;
    }
    void cut(string s, int start) // start是在下标start的元素的前边进行切割
    {
        if (start == s.size()) {
            res.push_back(path);
            return;
        }
        for (int i = start; i < s.size(); i++) // 从起点开始,遍历寻找子串终点
        {
            if (huiwen(s, start, i)) {
                string str = s.substr(start, i - start + 1);
                path.push_back(str);
                cut(s, i + 1);
                path.pop_back();
            }
        }
    }
    vector<vector<string>> partition(string s) {
        cut(s, 0);
        return res;
    }
};

总结

回溯可以看成N叉树
树的高度是递归深度,每一个树枝是一个路径(组合)
树的宽度是for循环遍历,选择不同的起点

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2301_79647020/article/details/140684881

代码随想录算法训练营第二十七天| leetcode39. 组合总和、leetcode40. 组合总和 ii、leetcode131. 分割回文串_喵的博客-爱代码爱编程

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

代码随想录训练营第27天|leetcode 39. 组合总和、40.组合总和ii、 131.分割回文串__忆昔的博客-爱代码爱编程

参考 代码随想录 题目一:LeetCode 39.组合总和 依旧是组合问题,只是稍有不同:第一点是集合元素通过数组给出,第二点是元素可以重复,第三点是不限制每个组合的元素个数。针对第一点,用原来的i指针来得到数组中的元

代码随想录算法训练营day27 | leetcode 39. 组合总和 40. 组合总和 ii 131. 分割回文串-爱代码爱编程

39. 组合总和(题目链接:力扣) 思路:排列组合的经典题目,此题不需要树层去重(题目说了无重复数组)。 vector<vector<int>> result; void backtracking(vector<int>& candidates, int start, vector<int>&a

算法训练营第47天|1143.最长公共子序列|1035.不相交的线|53. 最大子序和|392.判断子序列-爱代码爱编程

1143.最长公共子序列 思路:这道题比较难理解的是递推公式,要想明白状态转换和各个状态的意义。 如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1; 如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1

学习记录day18——数据结构 算法-爱代码爱编程

算法的相关概念         程序 = 数据结构 + 算法 算法是程序设计的灵魂,结构式程序设计的肉体 算法:计算机解决问题的方法护额步骤 算法的特性 1、确定性:算法中每一条语句都有确定的含义,不能模棱两可 2、有穷性:程序执行一段时间后会自动结束 3、输入:有零个或多个输入 4、输出:至少一个输出,可输出多个 5、可行性:经济可行性

代码随想录算法训练营第 22 天 |leetcode77. 组合 leetcode 216.组合总和iii leetcode17.电话号码的字母组合-爱代码爱编程

代码随想录算法训练营 Day22 代码随想录算法训练营第 22 天 |LeetCode77. 组合 LeetCode 216.组合总和III LeetCode17.电话号码的字母组合 目录 代码随想录

代码随想录算法训练营第23天|leetcode 39. 组合总和、40.组合总和ii、131.分割回文串-爱代码爱编程

1. LeetCode 39. 组合总和 题目链接:https://leetcode.cn/problems/combination-sum/description/ 文章链接:https://programmerc

codeforces round 961 (div. 2)-爱代码爱编程

A题:Diagonals 题意 给定一个n x n的网格,k个筹码,放在某个位置,则其对应的右上-左下对角线被占用,问占用的对角线数量最少是多少? 思路 模拟 每次我们都往格子最多的对角线上放,然后次多... 很容易看出来 代码 inline void solve() { int n, k; cin >> n >

1137. 第 n 个泰波那契数-爱代码爱编程

1137. 第 N 个泰波那契数 题目链接:1137. 第 N 个泰波那契数 代码如下: class Solution { public: int tribonacci(int n) {

代码随想录算法训练营day23||leetcode39.组合总和、leetcode40.组合总和Ⅱ、leetcode131.切割回文串-爱代码爱编程

一、组合总和         这题一开始没用startindex做,直接回溯穷举,导致最后类似【3,3,2】和【3,2,3】没有去重,用了startindex以后,就不会出现后面的数小于前面的数,只能是大于等于的情况,而大于这种情况本题允许取,所以可以是大于等于,且要注意,回溯函数的index要传入i,即当前遍历到的点的下标 class Solutio

代码随想录训练第二十天|leetcode39.组合总和、leetcode40.组合总和ii、leetcode131.分割回文串-爱代码爱编程

文章目录 39.组合总和思路回溯三部曲剪枝优化 40.组合总和II思路回溯三部曲 131.分割回文串思路回溯三部曲动态规划优化,后序补上 39.组合总和 给你一个 无重复元素 的整

代码随想录算法训练营第27天| leetcode 39. 组合总和、40.组合总和ii、131.分割回文串-爱代码爱编程

目录 Leetcode 39. 组合总和 Leetcode 40.组合总和II Leetcode 131.分割回文串 Leetcode 39. 组合总和 题目链接:Leetcode 39. 组合总和 题目描述:给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates

代码随想录算法训练营第二十七天| leetcode39.组合总和、leetcode40.组合总和ii、leetcode131.分割回文串-爱代码爱编程

LeetCode 39 组合总和 题目链接:39. 组合总和 【解题思路】 本题元素可以重复选取,因此剩余的集合就需要包括当前选取的元素。 【解题步骤】 主函数部分: 【全局变量】path一维数组用来存放单一节点 【全局变量】result二维数组用来存放结果集 调用递归函数,传入candidate,target,0,0 retur