代码随想录day23--回溯的应用2

LeetCode39.组合总和

题目描述:

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

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

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

示例 2:

输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]

示例 3:

输入: candidates = [2], target = 1
输出: []

解题思路:

·这题的解题思路与之前的题目是一致的,是需要注意的是,这题含有重复元素这一定义,所以,再遍历的过程中,startIndex不需要想后移动

代码如下:

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

·时间复杂度:O(n*2^n),注意这里只是时间复杂度的上界

·空间复杂度:O(target)

总结:这题与之前的题目有两点不同1.组合没有数量要求2.元素可无限重复选取

本题中使用startIndex来控制for循环的起始位置,对于组合问题中:

如果一个集合来求组合的话,就需要startIndex,例如之前写的77.组合,216.组合总和III

如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如之前的17.电话号码的字母组合

LeetCode40.组合总和II

题目描述:

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

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

注意:解集不能包含重复的组合。 

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

解题思路:

·本题的难点在于,集合中可以有重复元素,但是不能有重复的组合,有些同学的想法是使用map或者set进行去重,但是这样使用并不能通过,所以我们要在搜索过程中去掉重复组合

·有很多同学不理解这里去重的意思,可以这样理解,就是使用过的元素不能重复使用。说起来是很简单的,但是如果抽象成树结构那么就不好思考出了,因为在树结构上,存在两个维度,一个维度是同一树杈上使用过,一个维度是同一树层次上使用过

·又有新的问题了,那么到底是选择同一树层上的,还是同一树杈上的,题目中说了,可以有重复的元素,但是不能有重复的组合,就可以列一个简单的例子,自己将树结构抽象画图出来,就明白了,如图:

·所以,我们要去重的是同一数层上使用过的,同一树枝上的都是一个组合内的元素,不用去重。

*特别强调,在对数组操作前,要将数组内元素进行排序

·我们使用一个bool型数组used,用于记录同一树枝上的元素是否使用过,若为true则未使用过,反之则使用过,因为已经将元素排序,所以当candidates[i] == candidates[i-1]并且used[i-1] == false,就说明前一个树枝使用了candidates[i-1],也就是说同一数层使用过candidates[i-1],则跳出循环,进行下一次遍历

*文字描述比较抽象,配合图片一起食用

代码如下:

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

·时间复杂度:O(n*2^n)

·空间复杂度:O(n)

难点/易错点

·对元素去重的理解,是去除重复元素,还是去除重复组合

·没有对数组元素进行排序

·不知道如何确定元素是否被使用过

·停止搜索条件、递归条件、重复元素的定义

总结:因为这道题有去重这一步骤,所以这道题比之前做的回溯的题目更加的困难,关键是去重的逻辑,代码并不难理解,但是要把代码含义理解明白,这道题比较偏向逻辑,虽然是考察逻辑性,但是依旧是使用的回溯的基本模板。

LeetCode131.分割回文串

题目描述:

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

回文串 是正着读和反着读都一样的字符串。

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

解题思路:

·切割问题类似组合问题

例如字符串abcdef:

1.组合问题:选取一个a之后,再bcdef中再去选取第二个,选取b之后再cdef中再选取第三个...

2.切割问题:切割一个a之后,再bcdef中再去切割第二段,切割b之后在cdef中再切割第三段...

·所以我们就可以将切割问题抽象成一棵树形结构:

·递归用来纵向遍历,for循环用来横向遍历,切割线(图中红线)切割到字符串的结尾位置,说明找到了一个切割方法。所以我们就可以发现,切割问题的回溯搜索的过程和则核问题的回溯搜索的过程是差不多的。

代码如下:

class Solution {
public:
    vector<vector<string>> result;
    vector<string> path;
    void backtracking(const string& s,int startIndex){
        if(startIndex >= s.size()){
            result.push_back(path);
            return ;
        }
        for(int i = startIndex;i < s.size();i++){
            if(huiwen(s,startIndex,i)){
                string str = s.substr(startIndex,i-startIndex+1);
                path.push_back(str);
            }else{
                continue;
            }
            backtracking(s,i+1);
            path.pop_back();
        }
    }
    bool huiwen(const string& s,int start,int end){
        for(int i = start,j = end;i < j;i++,j--){
            if(s[i] != s[j]){
                return false;
            }
        }
        return true;
    }
    vector<vector<string>> partition(string s) {
        backtracking(s,0);
        return result;
    }
};

·时间复杂度:O(n*2^n)

·空间复杂度:O(n^2)

难点:

·切割问题可以抽象成组合问题

·如何模拟哪些切割线

·切割问题总递归如何终止

·在递归循环中如何截取子串

·如何判断回文

总结:这道题可以说啥比较有难度了,有很多同学包括我自己,遇到题目知道比较难,但是不知道题目难在哪里。但是这样说明思维不够清晰。

之前在说明回溯法基础的时候说明了回溯法可以解决切割问题,但是在做这题的时候第一个i难点就是:不知道如何切割,甚至也不知道在哪里需要使用回溯法。也就是没有体会到按照组合问题的套路就可以解决切割。

但是接下来如何模拟切割线,如何终止,如何截取子串,都不好想,可以说是判断回文是最简单的了。

并且,需要搞明白,关于模拟切割线,其实就是index是上一层已经确定了的分割线,i是这一层试图寻找的新分割线。搞懂了这些,这道题其实也就没有那么难了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RCS系统之:基础算法

设计仓库机器人的控制管理系统涉及到路径规划、任务分配、库存管理、通信系统等方面。以下是一个基本的仓库机器人控制管理系统方案的概述&#xff1a; 路径规划&#xff1a;设计一个路径规划系统&#xff0c;用于确定机器人在仓库内的最佳行驶路径&#xff0c;以最大程度地提…

optee TA文件签名

TA的签名 在optee_os目录下&#xff0c;存放着签名的私钥和签名脚本。 工程目录 optee_os/keys/default_ta.pem 工程目录 optee_os/scripts/sign_encrypt.py 编译TA时会先将TA编译为elf文件。此时执行签名脚本&#xff0c;对elf文件签名并生成.ta文件。 签名使用了RSA2048的 私…

及其详细的Markdown基础-学习笔记(附有使用案例)

Markdown 基础语法 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever 标题创建 标题语法格式 在文字前添加一至六个#即可创建标题 标题是有等级的&#xff0c;具体等级根据#个数决定 由于标题等级参与构建整篇文章的架构&#xff0c;编写时应该遵循如下规…

【C++航海王:追寻罗杰的编程之路】string类

目录 1 -> 为什么学习string类&#xff1f; 1.1 -> C语言中的字符串 2 -> 标准库中的string类 2.1 -> string类 2.2 -> string类的常用接口 3 -> string类的模拟实现 3.1 -> 经典的string类问题 3.2 -> 浅拷贝 3.3 -> 深拷贝 3.3.1 ->…

51_蓝桥杯_led流水灯

一 原理图分析 二 三八译码器工作原理 三八译码器&#xff1a;3个输入控制8路互斥的低电平有效输出。 C B A 输出 0 0 0 Y0 0 0 1 Y1 0 1 0 Y2 0 1 1 Y3 1 0 0 Y4 1 0 1 Y5 1 1 0 Y6 1 1 1 Y7 三 锁存器工作原理 锁存器&#xff1a;当使…

【报告解析】OpenAI Sora视频模型官方报告全解析 | 效果,能力以及基本原理

省流版 1 核心数据处理将视频数据整合成一个一个的Patch&#xff0c;方便统一训练数据&#xff0c;利用扩散Transformer架构 2 功能效果除了可以实现基础的文生视频外&#xff0c;实际上还有非常惊艳的视频延展&#xff0c;视频编辑&#xff0c;视频连接等多种功能&#xff0…

FPGA中的模块调用与例化

目录 一、模块调用与实例化 1.1 模块调用 1.2 模块实例化 1.3 Verilog例化语句及其用法 1.3.1 例化语句的基本格式 1.3.2 实例化三种不同的连接方法 二、模块调用实例-全加器与半加器 2.1 半加器模块 2.2 全加器模块 三、参数定义关键词与整数型寄存器 3.1 参数定义关…

第五节笔记:LMDeploy 大模型量化部署实践

大模型部署背景 参数用FP16半精度也就是2字节&#xff0c;7B的模型就大约占14G 2.LMDeploy简介 量化降低显存需求量&#xff0c;提高推理速度 大语言模型推理是典型的访问密集型&#xff0c;因为是decoder only的架构&#xff0c;需要token by token的生成&#xff0c;因…

设计模式Python实现

过年在家瞎折腾&#xff0c;闲着无聊看到设计模式&#xff0c;于是就想着用Python实现一下。 简单工厂 根据传入的参数决定创建出哪一种产品类的实例。 class CashFactory:def createCashAdapter(self, type):if type "满100减20":return CashReturn(100, 20)elif…

安全技能讲座 - 便携式灭火器 (Portable Fire Extinguishers )

【Transcript 】 火灾随时随地都可能发生&#xff0c;而且毫无征兆。如果您在家中或工作中遇到火灾&#xff0c;便携式灭火器可以帮助您保护自己&#xff0c;并有可能将火灾扼杀在摇篮中。本课程将向您介绍便携式灭火器、其工作原理和使用方法。成功完成本课程后&#xff0c;您…

C++--Linux基础使用

文章目录 几个简单命令开机关机重启查看当前目录切换当前目录列出当前目录下的目录和文件列出指定目录下的目录和文件清屏查看/设置时间 目录和文件目录概要目录详细说明相对路径和绝对路径 上古神器vi创建/打开文件vi 的两种模式vi 的常用命令 用户管理组管理用户管理修改用户…

每日一题——LeetCode1455.检查单词是否为句中其他单词的前缀

方法一 js函数slice() 将字符串按空格符分割为单词数组&#xff0c;记searchWord的长度为n&#xff0c;分割每个单词的前n位看是否和searchWord匹配 var isPrefixOfWord function(sentence, searchWord) {let res sentence.split(" ")for(i 0 ; i < res.lengt…

【Java EE初阶十二】网络原理(二)

2. 传输层 2.2 TCP协议 2.2.2 关于可靠传输 4.滑动窗口 前面的三个机制&#xff0c;都是在保证 tcp 的可靠性&#xff1b; TCP 的可靠传输,是会影响传输的效率的.(多出了一些等待 ack 的时间,单位时间内能传输的数据就少了)&#xff1b; 滑动窗口,就让可靠传输对性能的影响,更…

Linux:docker在线仓库(docker hub 阿里云)基础操作

把镜像放到公网仓库&#xff0c;这样可以方便大家一起使用&#xff0c;当需要时直接在网上拉取镜像&#xff0c;并且你可以随时管理自己的镜像——删除添加或者修改。 1.docker hub仓库 2.阿里云加速 3.阿里云仓库 由于docker hub是国外的网站&#xff0c;国内的对数据的把控…

2024年十大数字技术趋势与其安全挑战报告

今天分享的是行业报告&#xff1a;《2024年十大数字技术趋势与其安全挑战报告》 &#xff08;内容出品方&#xff1a;CSA GCR&#xff09; 报告共计&#xff1a;86页 来源&#xff1a;《见鹿报告》 序言 随着数字技术的迅猛发展,越来越多的组织和个人在数字化环境中开展业…

【IIS中绑定SSL证书】

下载SSL证书&#xff1a; 打开服务器IIS&#xff1a; 点击导入 在IIS中新增网站&#xff1a;

2024年【天津市安全员B证】考试技巧及天津市安全员B证复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年天津市安全员B证考试技巧为正在备考天津市安全员B证操作证的学员准备的理论考试专题&#xff0c;每个月更新的天津市安全员B证复审模拟考试祝您顺利通过天津市安全员B证考试。 1、【多选题】《建设行政处罚决定…

常见的几种Web安全问题测试简介

Web项目比较常见的安全问题 1.XSS(CrossSite Script)跨站脚本攻击 XSS(CrossSite Script)跨站脚本攻击。它指的是恶意攻击者往Web 页面里插入恶意html代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中Web 里面的html 代码会被执行&#xff0c;从而达到恶意用户的特殊…

论文解读:Masked Generative Distillation

文章汇总 话题 知识蒸馏 创新点 带掩盖的生成式蒸馏 方法旨在通过学生的遮罩特征来生成老师的特征(通过遮盖学生部分的特征来生成老师的特征)&#xff0c;来帮助学生获得更好的表现 输入:老师:&#xff0c;学生:&#xff0c;输入:&#xff0c;标签:&#xff0c;超参数: 1:使…

多模态学习综述(MultiModal Learning)

最早开始关注到多模态机器学习是看到Jeff Dean在2019年年底NeurIPS大会上的一个采访报道&#xff0c;讲到了2020年机器学习趋势&#xff1a;多任务和多模态学习将成为突破口。 Jeff Dean 谈2020年机器学习趋势&#xff1a;多任务和多模式学习将成为突破口 站在2022年&#xff…