首页 > 编程语言 >代码随想录算法训练营第 23 天 |LeetCode 39. 组合总和 LeetCode 40.组合总和II LeetCode131.分割回文串

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

时间:2024-07-25 12:25:46浏览次数:22  
标签:组合 int 随想录 start vector candidates path LeetCode 总和

代码随想录算法训练营

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


目录


前言

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循环都要检查现在起点是否出现过

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循环遍历,选择不同的起点

标签:组合,int,随想录,start,vector,candidates,path,LeetCode,总和
From: https://blog.csdn.net/2301_79647020/article/details/140684881

相关文章

  • 代码随想录算法训练营第 22 天 |LeetCode77. 组合 LeetCode 216.组合总和III LeetCode
    代码随想录算法训练营Day22代码随想录算法训练营第22天|LeetCode77.组合LeetCode216.组合总和IIILeetCode17.电话号码的字母组合目录代码随想录算法训练营前言LeetCode77.组合LeetCode216.组合总和IIILeetCode17.电话号码的字母组合一、基础1、回溯可以解......
  • 代码随想录算法训练营第二十二天|回溯算法part01
    第77题.组合在单个集合1-n中,寻找所有个数为k的组合。和所有递归一样,都有三部曲。确定参数与返回值确定终止条件单层逻辑首先,回溯算法的返回值一般是void,参数依照题目要求而增加,在这一题中,参数有n,k还有startIndex。终止条件是path的size等于k,将path存放在result中。......
  • 代码随想录算法训练营第43天 | 动态规划7:买卖股票
    121.买卖股票的最佳时机https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/代码随想录https://programmercarl.com/0121.买卖股票的最佳时机.html#算法公开课and-sell-stock/description/122.买卖股票的最佳时机IIhttps://leetcode.cn/problems/be......
  • 代码随想录算法训练营第42天 | 动态规划7:打家劫舍入门
    打家劫舍https://leetcode.cn/problems/house-robber/description/代码随想录https://programmercarl.com/0198.打家劫舍.html打家劫舍-环形https://leetcode.cn/problems/house-robber-ii/description/代码随想录https://programmercarl.com/0213.打家劫舍II.html#思路......
  • LeetCode122. 买卖股票的最佳时机 II
    题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/题目叙述:给你一个整数数组prices,其中prices[i]表示某支股票第i天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候最多只能持有一股股票。你也可以先购买,然后......
  • LeetCode 热题 HOT 100 (007/100)【宇宙最简单版】
    【数组】No.0215数组中第k个最大的元素【中等】......
  • LeetCode860. 柠檬水找零
    题目链接:https://leetcode.cn/problems/lemonade-change/description/题目叙述:在柠檬水摊上,每一杯柠檬水的售价为5美元。顾客排队购买你的产品,(按账单bills支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付5美元、10美元或20美元。你必须给每个顾客正确找零,......
  • 代码随想录 day34 不同路径 | 不同路径 II
    不同路径不同路径解题思路通过动态规划,先将第一行和第一列设为1,目的是初始化dp,这样设置的理由是这些格子只有一条路能达到,接着就是遍历整个路径,每个格子所包含的路径和为其左边和上边的路径数之和,随后在目的地格子得到值。知识点动态规划心得没想到初始化的方式,导致没有实......
  • LeetCode455.分发饼干
    LeetCode题目链接:https://leetcode.cn/problems/assign-cookies/description/题目叙述假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子i,都有一个胃口值g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干j,都有一个尺......
  • 每日一题:Leetcode-32 最长有效括号
    力扣题目解题思路java代码力扣题目:给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。示例1:输入:s="(()"输出:2解释:最长有效括号子串是"()"示例2:输入:s=")()())"输出:4解释:最长有效括号子串是"()()"示例3:输入:s=""......