代码随想录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是这一层试图寻找的新分割线。搞懂了这些,这道题其实也就没有那么难了。

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

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

相关文章

PyQt Python 使用 VTK ITK 进行分割 三维重建 医学图像可视化系统 流程

效果&#xff1a; 重建流程&#xff1a; 1. 输入 可以读取DICOM &#xff0c;nii nrrd 等数据 设置读取器以加载 DICOM 图像系列。 使用 itk::GDCMImageIO 作为 DICOM 图像的输入输出接口。 使用 itk::GDCMSeriesFileNames 获取指定路径下的所有 DICOM 文件名。 使…

Code Composer Studio (CCS) - Current and Local Revision

Code Composer Studio [CCS] - Current and Local Revision References 鼠标放在文件内的任意位置&#xff0c;鼠标右键 -> Compare With -> Local History -> Revision Time. References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

Doris ——SQL原理解析

目录 前言 一、Doris简介 二、SQL解析简介 2.1 词法分析 2.2 语法分析 2.3 逻辑计划 2.4 物理计划 三、Doris SQL解析的总体架构 四、Parse阶段 五、Analyze阶段 六、SinglePlan阶段&#xff08;生成单机逻辑Plan阶段&#xff09; 七、DistributedPlan计划&#xf…

SQL-Labs靶场“11-15”关通关教程

君衍. 一、十一关 基于POST单引号字符型注入1、源码分析2、联合查询注入3、报错注入 二、十二关 基于POST双引号字符型注入1、源码分析2、联合查询注入3、报错注入 三、十三关 基于POST单引号报错注入变形1、源码分析2、报错注入 四、十四关 基于POST双引号报错注入1、源码分析…

代码随想录day24--回溯的应用3

LeetCode93.修复IP地址 题目描述&#xff1a; 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是…

Chapter 8 - 15. Congestion Management in TCP Storage Networks

User Actions After learning the states of queue utilization, the following are the actions that admins and operators can take while using TCP transport for storage traffic. 了解了队列利用率的状态后,管理员和操作员在使用 TCP 传输存储流量时可以采取以下措施。…

使用八叉树模拟水和烟雾 Simulating Water and Smoke with an Octree Data Structure 论文阅读笔记

原文&#xff1a; Losasso, Frank, Frdric Gibou, and Ron Fedkiw. “Simulating water and smoke with an octree data structure.” Acm siggraph 2004 papers. 2004. 457-462. 引言 这篇文章扩展了 [Popinet 2003] 的工作&#xff0c;拓展到表面自由流&#xff0c;并且使…

Oracle 基础入门指南

一、什么是Oracle&#xff1f; Oracle是一款由美国Oracle公司开发的关系型数据库管理系统。它支持SQL查询语言&#xff0c;并提供了丰富的功能和工具&#xff0c;用于管理大规模数据存储、处理和访问。Oracle被广泛应用于企业级应用中&#xff0c;包括金融、电信、零售等各行各…

第12章 反射

12.1 反射概述 Java的反射&#xff08;reflection&#xff09;机制是指在程序的运行状态中&#xff0c;可以构造任意一个类的对象&#xff0c;可以得到任意一个对象所属的类的信息&#xff0c;可以调用任意一个类的成员变量和方法&#xff0c;可以获取任意一个对象的属性和方法…

突破编程_C++_高级教程(多线程编程实例)

1 生产者-消费者模型 生产者-消费者模型是一种多线程协作的设计模式&#xff0c;它主要用于处理生产数据和消费数据的过程。在这个模型中&#xff0c;存在两类线程&#xff1a;生产者线程和消费者线程。生产者线程负责生产数据&#xff0c;并将其放入一个共享的数据缓冲区&…

Java中 ConcurrentSkipListSet和ConcurrentSkipListMap的区别

ConcurrentSkipListSet和ConcurrentSkipListMap之间有什么区别 ConcurrentSkipListSet和ConcurrentSkipListMap都是Java并发包java.util.concurrent中的类&#xff0c;它们都使用"Skip List"&#xff08;跳表&#xff09;数据结构。跳表是一种随机化数据结构&#x…

【nginx实践连载-1】安装部署配置初始化

要在Ubuntu上安装、部署和配置Nginx&#xff0c;可以按照以下步骤进行操作&#xff1a; 步骤1&#xff1a;安装Nginx 打开终端&#xff08;Terminal&#xff09;。运行以下命令更新软件包索引&#xff1a;sudo apt update安装Nginx&#xff1a;sudo apt install nginx步骤2&a…

Python常见的字符串格式化

Python中字符串格式化有多种方式&#xff0c;以下是其中常用的几种&#xff1a; 使用%进行格式化&#xff1a;类似于C语言中的printf方式。 name "Alice" age 11 message "Hello, %s! You are %d years old." % (name, age) print(message)使用format()…

js---webAPI

01 声明变量 js组成&#xff1a; DOM:操作网页内容的,开发页面内容特效和实现用户交互 BOM: DOM树&#xff1a;将 HTML 文档以树状结构直观的表现出来&#xff0c;我们称之为文档树或 DOM 树 文档树直观的体现了标签与标签之间的关系 CSS获取元素的方法 document.querySele…

态、势、感、知的偏序、全序与无序

在态势感知中&#xff0c;"态"、"势"、"感"和"知"可以被理解为描述不同层次的概念。而在偏序、全序和无序方面&#xff0c;它们可以有不同的关系&#xff0c;简单地说&#xff0c;偏序关系表示部分的可比较性&#xff0c;全序关系表示…

精品springboot基于大数据的电脑主机硬件选购助手-可视化大屏

《[含文档PPT源码等]精品基于springboot基于大数据的电脑主机硬件选购助手[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; Java——涉及技术&#xff1a; 前端使用技术&a…

Cron表达式选择器

Cron表达式选择器 功能描述 Cron表达式选择器是用于定时任务调度的一种常见工具&#xff0c;通常用于指定任务的执行时间。Cron表达式由一系列时间单位和对应的时间值组成&#xff0c;用于指定任务的执行时间。下面是一个Cron表达式的示例 0 0 12 * * ?这个表达式的含义是每…

有一台阿里云轻量应用服务器可以用来做什么?

阿里云轻量应用服务器可以用来做什么&#xff1f;轻量服务器可用于网站搭建、个人博客、图床、云端学习环境、电商建设、论坛社区、开发环境配置等。可以在阿里云CLUB中心查看 aliyun.club 当前最新的优惠券和活动信息。 轻量是不是性能差&#xff1f;不是&#xff0c;轻量应用…

电阻器的脉冲浪涌能力?

由于现有需求&#xff0c;许多现代电子电路和设备都会经历瞬态脉冲和浪涌。这反过来又导致需要“设计”瞬态浪涌保护&#xff0c;尤其是在电机控制器等电路中。当电机启动时&#xff0c;此时消耗的电流过大&#xff0c;可能导致电阻器故障。同样&#xff0c;如果电容器用于电机…

洛谷: P1480 A/B Problem

题目描述 输入两个整数 a , b a,b a,b&#xff0c;输出它们的商。 输入格式 两行&#xff0c;第一行是被除数&#xff0c;第二行是除数。 输出格式 一行&#xff0c;商的整数部分。 样例 #1 样例输入 #1 10 2样例输出 #1 5提示 0 ≤ a ≤ 1 0 5000 0\le a\le 10^{500…