代码随想录训练营Day 29|力扣39. 组合总和、40.组合总和II、131.分割回文串

news2024/11/15 15:28:56

1.组合总和

题目链接/文章讲解: 代码随想录

视频讲解:带你学透回溯算法-组合总和(对应「leetcode」力扣题目:39.组合总和)| 回溯法精讲!_哔哩哔哩_bilibili

代码:(未剪枝版 )

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& candidates,int target,int startIndex){
        // 递归出口
        if(target < 0){
            return;
        }
        if(target == 0){
            result.push_back(path);
            return;
        }
        // 处理结点
        for(int i = startIndex;i < candidates.size();i++){
            target -= candidates[i];
            path.push_back(candidates[i]);
            backtracking(candidates,target,i);
            path.pop_back();
            target += candidates[i];
        }
    }
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        if(candidates.size() == 0) return result;
        backtracking(candidates,target,0);
        return result;
    }
};

 代码:(剪枝版)

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& candidates,int target,int startIndex){
        // 递归出口
        if(target < 0){
            return;
        }
        if(target == 0){
            result.push_back(path);
            return;
        }
        // 处理结点
        // 这里加了判断:如果下一轮的target已经小于0了,就没有必要递归了
        for(int i = startIndex;i < candidates.size() && target - candidates[i] >= 0;i++){
            target -= candidates[i];
            path.push_back(candidates[i]);
            backtracking(candidates,target,i);
            path.pop_back();
            target += candidates[i];
        }
    }
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        if(candidates.size() == 0) return result;
        sort(candidates.begin(), candidates.end()); // 涉及大小的剪枝必排序
        backtracking(candidates,target,0);
        return result;
    }
};

思路:学到了这种元素数量不限制的取的解法

其实startIndex变量还是要有,因为我们求的是组合,要数层去重;并且这是在同一个数组里取数。

而数量不限,体现在我在递归里传入的starIndex的值是i,而不是i+1了。之前说过for循环管控每一层数的宽度;递归则管控数的深度。这样更改后,就可以在取完一个数的情况后,继续取这个数。实现如下图所示的效果:

关于剪枝的操作。这种涉及到总和大小的取值时。剪枝就要将给定的数组排序! 而且要注意给定的数组元素里全是正数,只有正数才越加越大。

这道题,我直接用目标总和target取减去每一个结点的数值了,看最后是否被减为0了。

2.组合总和2 

 题目链接/文章讲解:代码随想录

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

 代码:去重且剪枝过的

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& candidates,int target,int startIndex,vector<bool>& used){
        if(target < 0){
            return;
        }
        if(target == 0){
            result.push_back(path);
            return;
        }
        for(int i = startIndex;i < candidates.size() && target - candidates[i] >= 0;i++){
            // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
            // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
            // 要对同一树层使用过的元素进行跳过
            if(i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false){
                continue;
            } // 数层去重
            used[i] = true;
            target -= candidates[i];
            path.push_back(candidates[i]);
            backtracking(candidates,target,i + 1,used);
            path.pop_back();
            target += candidates[i];
            used[i] = false;
        }
    }
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<bool> used(candidates.size(),false);
        sort(candidates.begin(),candidates.end());
        backtracking(candidates,target,0,used);
        return result;
    }
};

思路:

这道题和上题的区别是:

每个元素只能使用一次——startIndex为i+1;

给定的元素有重复值,但是要去重后的结果:这里就是难点。首先去重是有两个维度的。

 一个组合里可以有相同大小的不同元素,所以递归操作里不需要去重,即上图的同一个子树的数枝上不需要去重;不同组合不能相同,所以要在数层去重。

这里用一个数组used来记录,遇到的和前一个元素相同的情况(这里去重先去把给定数组排序)时,到底是和前一个相同元素是在同一个树枝里的,还是同一个树层里的。

在同一个树枝里:前一个元素已经加入到了path里,已经使用过了。

在同一个树层里:前一个元素没有加入到path里,没有被使用,这是独立的两个分支。

所以如果遇到这种树层里重复的情况,加个判断语句,直接continue(因为接下来的情况还有我们要收集的,所以只是跳过这一种情况,用continue)

3.分割回文串

代码随想录

视频讲解:带你学透回溯算法-分割回文串(对应力扣题目:131.分割回文串)| 回溯法精讲!_哔哩哔哩_bilibili

 代码:

class Solution {
private:
    vector<string> path;
    vector<vector<string>> result;
    bool isPalindrome(string& s,int start,int end){
        while(start <= end){
            if(s[start] != s[end]){
                return false;
            }
            start++;
            end--;
        }
        return true;
    }
    void backtracking(string& s,int startIndex){
        // 递归出口
        if(startIndex >= s.size()){
            result.push_back(path);
            return;
        }
        // 遍历结点
        // 回文子串的范围是[startIndex,i]
        for(int i = startIndex;i < s.size();i++){
            // 在这里直接判断是否子串满足回文子串
            if(isPalindrome(s,startIndex,i)){
                string str = s.substr(startIndex,i - startIndex + 1);
                path.push_back(str);
            }else{
                continue;
            }
            backtracking(s,i + 1);
            path.pop_back();
        }
    }
public:
    vector<vector<string>> partition(string s) {
        if(s.size() == 0) return result;
        backtracking(s,0);
        return result;
    }
};

思路:

关于substr函数:

这道题很巧妙地将startIndex作为了子串的开始下标,子串的范围可以表示为[startIndex,i]。

同时,本题将判断条件放在了for循环的里面来判断,来决定是否要执行下面的递归回溯操作。判断用了一个额外的函数来判断回文子串。 

细节问题其实就这些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1679918.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React Native 之 原生组件和核心组件(二)

原生组件 在 Android 开发中是使用 Kotlin 或 Java 来编写视图&#xff1b;在 iOS 开发中是使用 Swift 或 Objective-C 来编写视图。在 React Native 中&#xff0c;则使用 React 组件通过 JavaScript 来调用这些视图。在运行时&#xff0c;React Native 为这些组件创建相应的 …

19个测试⽤例⽣成的AI⼯具!卷起来!

在不断发展的软件开发领域中&#xff0c;确保应⽤程序的可靠性和功能性⾄关重要。 随着软件系统复杂性的增加&#xff0c;有效测试⽅法的需求也在上升。 传统的测试⽤例⽣成⽅法通常⽆法满⾜快速开发周期和复杂代码库的需求。 随着进⼊⼈⼯智能&#xff08;AI&#xff09;时…

ROS学习笔记(15)小车巡墙驾驶

0.前提 前一章我讲解了拉氏变换和PID&#xff0c;这一章我来讲解一下小车巡墙驾驶的理论和部分代码。 1.前情回顾 1.拉氏变换 拉普拉斯变换是要将时域问题转换成频域问题来处理。 2.PID控制器 转向角&#xff1a; 误差牺牲&#xff1a; 3.具体参看上一篇文章 2.巡墙驾驶…

机器学习入门介绍

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 目录 三大方向机器学习产生的原因机器如何学习…

Vue3学习笔记 - 禹神YYDS

1. 教程介绍 https://www.bilibili.com/video/BV1Za4y1r7KE?p1 本篇vue3&#xff0c;内容比较新&#xff0c;比如有setup语法糖用法&#xff1b;只是他使用TS&#xff0c;并不是JS&#xff1b;不过JS也比较熟悉了&#xff0c;也可以学习下TS的语法&#xff0c;课程使用 TypeSc…

【利用数组处理批量数据-谭浩强配套】(适合专升本、考研)

无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 完整资料如下&#xff1a;纯干货、纯干货、纯干货&#xff01;&#xff01;…

再谈毕业论文设计投机取巧之IVR自动语音服务系统设计(信息与通信工程专业A+其实不难)

目录 举个IVR例子格局打开&#xff0c;万物皆能IVR - 把《民法典》搬上IVR IVR系统其实可盐可甜。还能可圈可点。 戎马一生&#xff0c;归来依然IVR。 举个IVR例子 以下是IVR系统的一个例子。 当您拨打电话进入IVR系统。 首先检验是否为工作时间。 如是&#xff0c;您将被送入…

STM32F407 2个高级定时器生成2路无刷电机波形以及相电流采集程序(寄存器版)

stm32f407 高级定时1、定时8 生成20k 中心PWM 波形 并分别用其通道4 触发ADC1 ADC2 采样 用于分别两无刷电机foc 电流环控制&#xff0c;ADC1产生50us的电流采集完成中断&#xff0c;用于foc算法周期运算 主要参考高级定时器的寄存器和ADC寄存器 首先&#xff0c;要使用STM32F…

OSG编程指南<二十三>:基于OSG+ImGui制作模型编辑器,实现三轴方向的实时平移、旋转和缩放变化

1、概述 在OSG的开发应用过程中&#xff0c;我们有时候总会纠结于使用MFC还是Qt来嵌入OSG窗口以便于后续的功能开发&#xff0c;毕竟选择一个合适的UI框架&#xff0c;对于后续的开发还是省去很多麻烦的。但对于初学者来说&#xff0c;可能对框架消息机制的不熟悉&#xff0c;尤…

每日复盘-20240515

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 国联证券 (1)|[9:25]|[133765万]|31.12 一…

selenium发展史

Selenium Core 2004 年&#xff0c;Thoughtworks 的工程师 Jason Huggins 正在负责一个 Web 应用的测试工作&#xff0c;由于这个项目需要频繁回归&#xff0c;这导致他不得不每天做着重复且低效的工作。为了解决这个困境&#xff0c;Jason 开发了一个运行在 JavaScript 沙箱中…

表白成功率百分百的向女朋友表白网页源代码,向女友表白HTML源代码

表白成功率百分百的向女朋友表白网页源代码&#xff0c;向女友表白HTML源代码 效果&#xff1a; 完整代码下载地址&#xff1a;向女友表白HTML源代码 <!DOCTYPE html> <!--STATUS OK--> <html><head><meta http-equiv"Content-Type" c…

Linux|基础环境开发工具使用(1)

目录 Linux 软件包管理器 yum 什么是软件包 关于 rzsz 注意事项 查看软件包 如何安装软件 如何卸载软件 Linux编辑器-vim介绍 vi与vim的相同点 vi与vim区别 Linux 软件包管理器 yum 什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译…

【Windows】回忆Win98

回忆Win98&#xff0c;又看到了这个Excel界面&#xff0c;上次还是十多年前的计算机课上 1、安装环境 Win11家庭版,23H2,VMware Workstation Pro 16 , 2、安装步骤及参考 虚拟机里的硬盘设置成SATA&#xff08;否则各种错误&#xff09;&#xff0c;安装MSDOS7.1&#xff…

VP Codeforces Round 944 (Div 4)

感受&#xff1a; A~G 其实都不难&#xff0c;都可以试着补起来。 H看到矩阵就放弃了。 A题&#xff1a; 思路&#xff1a; 打开编译器 代码&#xff1a; #include <iostream> #include <vector> #include <algorithm> #define int long long using na…

基于Springboot的学生心理压力咨询评判(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的学生心理压力咨询评判&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

【Unity之FairyGUI】你了解FGUI吗,跨平台多功能高效UI插件

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

免费体验GPT-4o这5大功能,非常好用!

这几天&#xff0c;OpenAI发布了新的GPT版本&#xff0c;GPT-4o&#xff0c;比GPT4更加智能也更快。 据说&#xff0c;GPT-4o在文本、推理和编码智能方面实现了GPT-4 Turbo级别的性能&#xff0c;在多语言、文本、音频和视觉功能方面甚至超过了市面上所有同类产品。 有几个亮点…

Anaconda安装-超详细版(2024)

扫盲&#xff1a;先装Python还是先装anaconda? 安装anaconda即可&#xff0c;不需要单独装python anaconda 是一个python的发行版&#xff0c;包括了python和很多常见的软件库, 和一个包管理器conda。 一、下载Anaconda 安装包&#xff08;官网和国内镜像资源&#xff09; …

SpringBoot之远程调用的三大方式

为什么要使用远程调用&#xff1f; SpringBoot不仅继承了Spring框架原有的优秀特性&#xff0c;而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。在Spring-Boot项目开发中&#xff0c;存在着本模块的代码需要访问外面模块接口&#xff0c;或外部url链接的需求…