算法打卡day23|回溯法篇03|Leetcode 39. 组合总和、40.组合总和II、131.分割回文串

 算法题

Leetcode 39. 组合总和

题目链接:39. 组合总和

大佬视频讲解:组合总和视频讲解

 个人思路

这道组合题主要是有总和的限制,当递归和超过了总和就return,递归时加上回溯去遍历数组。

解法
回溯法

把组合问题抽象为如下树形结构

如上图,因为本题没有组合数量要求,仅仅是总和的限制,所以递归没有层数的限制只要选取的元素总和超过target,就返回

回溯法三部曲

1.递归函数参数

定义两个全局变量,二维数组result存放结果集,数组path存放符合条件的结果。

首先是题目中给出的参数,集合candidates, 和目标值target。

此外还需要定义int型的sum变量来统计单一结果path里的总和,startIndex来控制for循环的起始位置.

关于startIndex的使用:如果是一个集合来求组合的话,就需要startIndex,比如组合三。如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例子:Leetcode 77.组合

2.递归终止条件

终止只有两种情况,sum大于target和sum等于target。sum等于target的时候,需要收集结果

3.单层搜索的逻辑

单层for循环依然是从startIndex开始,搜索candidates集合。

本题元素为可重复选取的。所以在递归时,i不需要加1

剪枝

这道题的剪枝就是对总集合排序之后,如果下一层的sum(就是本层的 sum + candidates[i])已经大于target,就可以结束本轮for循环的遍历

class Solution {public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> res = new ArrayList<>();Arrays.sort(candidates); // 先进行排序backtracking(res, new ArrayList<>(), candidates, target, 0, 0);return res;}public void backtracking(List<List<Integer>> res, List<Integer> path, int[] candidates, int target, int sum, int idx) {// 找到了数字和为 target 的组合if (sum == target) {res.add(new ArrayList<>(path));return;}for (int i = idx; i < candidates.length; i++) {// 如果 sum + candidates[i] > target 就终止遍历if (sum + candidates[i] > target) break;//剪枝path.add(candidates[i]);backtracking(res, path, candidates, target, sum + candidates[i], i);path.remove(path.size() - 1); // 回溯,移除路径 path 最后一个元素}}
}

时间复杂度:O(n * 2^n));(循环n个元素,2^n表示所有可能的子集数量)

空间复杂度:O(n);(递归栈的深度最多为 n)


 Leetcode  40.组合总和II

题目链接:40.组合总和II

大佬视频讲解:组合总和II视频讲解

个人思路

这道题的集合(数组candidates)有重复元素,但还不能有重复的组合,这是这道题难的关键,思路就是 用一个标记数组标记该元素层次上是否使用过,使用过的就跳过,这样不会出现重复的组合。

解法
回溯法

把组合问题抽象为如下树形结构:

“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过

元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同所以要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。(强调:树层去重的话,需要对数组排序!)

回溯法三部曲

1.递归函数参数

除开存放数组的集合和符合条件的路径, 这道题需要加一个bool型数组used,用来记录同一树枝上的元素是否使用过。这个集合去重的重任就是used来完成的。

2.递归终止条件

终止条件为 sum > target 和 sum == target

其中sum > target 这个条件可以省略,因为在递归单层遍历的时候,会有剪枝的操作.

3.单层搜索的逻辑

如抽线的树形结构,要去重的是“同一树层上的使用过”,判断逻辑如下:

如果candidates[i] == candidates[i - 1] 并且 used[i - 1] == false,就说明:前一个树枝,使用了candidates[i - 1],也就是说同一树层使用过candidates[i - 1]。此时for循环里就应该做continue的操作

所以值为 used[i - 1] == true,说明同一树枝candidates[i - 1]使用过

used[i - 1] == false,说明同一树层candidates[i - 1]使用过

因为同一树层,used[i - 1] == false 才能表示,当前取的 candidates[i] 是从 candidates[i - 1] 回溯而来的。而 used[i - 1] == true,说明是进入下一层递归,去下一个数,所以是树枝上

剪枝

当和大于目标值直接返回,即sum + candidates[i] <= target为剪枝操作

class Solution {LinkedList<Integer> path = new LinkedList<>();List<List<Integer>> ans = new ArrayList<>();boolean[] used;int sum = 0;public List<List<Integer>> combinationSum2(int[] candidates, int target) {used = new boolean[candidates.length];// 加标志数组,用来辅助判断同层节点是否已经遍历Arrays.fill(used, false);// 为了将重复的数字都放到一起,所以先进行排序Arrays.sort(candidates);backTracking(candidates, target, 0);return ans;}private void backTracking(int[] candidates, int target, int startIndex) {if (sum == target) {ans.add(new ArrayList(path));}for (int i = startIndex; i < candidates.length; i++) {if (sum + candidates[i] > target) {break;}// 出现重复节点,同层的第一个节点已经被访问过,所以直接跳过if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {continue;}used[i] = true;sum += candidates[i];path.add(candidates[i]);// 每个节点仅能选择一次,所以从下一位开始backTracking(candidates, target, i + 1);used[i] = false;sum -= candidates[i];path.removeLast();}}
}

时间复杂度:O(n * 2^n));(循环n个元素,2^n表示所有可能的子集数量)

空间复杂度:O(n);(递归栈的深度最多为 n)


 Leetcode  131.分割回文串

题目链接:131.分割回文串

大佬视频讲解:分割回文串视频讲解

 个人思路

既要判断是否为回文子串,还要切割,只能用回溯法了,但不知道如何切割,这是个问题...

解法
回溯法

把组合问题抽象为如下树形结构

其实本题的切割问题类似组合问题

例如对于字符串abcdef:

  • 组合问题:选取一个a之后,在bcdef中再去选取第二个,选取b之后在cdef中再选取第三个.....
  • 切割问题:切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中再切割第三段.....

回溯法三部曲

1.递归函数参数

全局变量数组path存放切割后回文的子串,二维数组result存放结果集。 

本题递归函数参数还需要startIndex,因为切割过的地方,不能重复切割

2.递归函数终止条件

按照切割的思想去看,切割线切到了字符串最后面,说明找到了一种切割方法,此时就是本层递归的终止条件。

那么在代码里什么是切割线呢?其实在处理组合问题的时候,递归参数需要传入startIndex,表示下一轮递归遍历的起始位置,这个startIndex就是切割线

3.单层搜索的逻辑

for (int i = startIndex; i < s.size(); i++)循环中,我们 定义了起始位置startIndex,那么 [startIndex, i] 就是要截取的子串

首先判断这个子串是不是回文,如果是回文,就加入path中,path用来记录切割过的回文子串。

注意切割过的位置,不能重复切割,所以,backtracking(s, i + 1); 传入下一层的起始位置为i + 1

判断回文子串

可以使用双指针法,一个指针从前向后,一个指针从后向前,如果前后指针所指向的元素是相等的,就是回文字符串了。

这里需要一个个判断

class Solution {List<List<String>> result= new ArrayList<>();//结果集Deque<String> path = new LinkedList<>();public List<List<String>> partition(String s) {backTracking(s, 0);return result;}private void backTracking(String s, int startIndex) {//如果起始位置大于s的大小,说明找到了一组分割方案if (startIndex >= s.length()) {result.add(new ArrayList(path));return;}for (int i = startIndex; i < s.length(); i++) {//如果是回文子串,则记录if (isPalindrome(s, startIndex, i)) {String str = s.substring(startIndex, i + 1);path.addLast(str);} else {continue;}backTracking(s, i + 1);//起始位置后移,保证不重复path.removeLast();}}//判断是否是回文串private boolean isPalindrome(String s, int startIndex, int end) {for (int i = startIndex, j = end; i < j; i++, j--) {if (s.charAt(i) != s.charAt(j)) {return false;}}return true;}
}

时间复杂度:O(n * 2^n));(循环n个元素,2^n表示所有可能的子集数量)

空间复杂度:O(n);(递归栈的深度最多为 n)


 以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

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

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

相关文章

达源电机超高速数码马达震撼来袭

新质生产力是什么? 12万转高速电吹风机马达引领行业技术革新 随着科技的不断进步&#xff0c;电吹风机行业正迎来一场深刻新质生产力技术革新。在这场革新中&#xff0c;达源电机以其独特绕线技术与自适应平衡磁场的马达技术&#xff0c;成功打破了国外高速马达电机悬臂梁专利…

uniapp——第3篇:自定义组件、组件间传数据

前提&#xff0c;建议先学会前端几大基础&#xff1a;HTML、CSS、JS、Ajax&#xff0c;还有一定要会Vue!&#xff08;Vue2\Vue3&#xff09;都要会&#xff01;&#xff01;&#xff01;不然不好懂 一、组件是啥玩意&#xff1f; 我之前讲vue2的文章讲过 Vue全家桶:vue2vue3全…

位图与布隆过滤器

目录 一、位图 1、问题用位图来解决&#xff1a; 二、 布隆过滤器 1、将哈希与位图结合&#xff0c;即布隆过滤器 2.布隆过滤器的查找 3.布隆过滤器的删除 4.布隆过滤器优点 5、布隆过滤器缺陷 三、海量数据处理问题&#xff1a; 一、位图 问题1&#xff1a;给40亿个不…

netron:本地查看服务器端打开的onnx文件

我们开发一般都在服务器中开发&#xff0c;假如我们在服务器端导出了一个onnx文件&#xff0c;不将onnx文件传到本地&#xff0c;如何进行本地查看呢&#xff1f; netron --port 8082 --host 10.75.29.201 model_data/deeplab_0131.onnx--host : 指定服务器的ip, 注意不是本地…

2024/03/19(网络编程·day5)

一、思维导图 二、selec函数实现TCP并发服务器 #include<myhead.h>#define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.117.116" //服务器IP int main(int argc, const char *argv[]) {//1、创建一个套接字int sfd -1;sfd socket(AF_INET,SOC…

软件设计师:03 - 数据库系统

一、数据模型的分类 1.1、概念数据模型 1.2、结构数据模型 1.3 真题 二、三级模式 概念模式对应的是基本表&#xff0c;概念模式也称为模式 外模式对应的是视图&#xff0c;也称用户模式或者子模式 内模式对应的是数据库里面的存储文件&#xff0c;也称存储模式 真题 三、两级…

VO、RVO、ORCA(动态避障)算法

碰撞锥&#xff08;碰撞区域&#xff09; 上上图中假设B物体处于静止状态&#xff0c;A物体沿着向量v1和v2移动&#xff0c;刚好能和B擦肩而过&#xff0c;不会发生碰撞&#xff1b;若V1和V2的夹角再小一点的话就一定会发生碰撞。此时会产生碰撞区域&#xff1a; 红线画出来…

蓝桥杯练习04学生成绩统计

学生成绩统计 介绍 随着大数据的发展&#xff0c;数据统计在很多应用中显得不可或缺&#xff0c;echarts作为一款基于JavaScript的数据可视化图表库&#xff0c;也成为了前端开发的必备技能&#xff0c;下面我们一起来用echarts开发一个学生数据统计的柱形图。 准备 开始答…

Vmware使用ubuntu报错空间不够

Vmware使用ubuntu报错空间不够 1.vmware修改2.进入镜像进行修改2.1需要下载GParted软件 1.vmware修改 这个需要把硬盘的大小进行扩展 2.进入镜像进行修改 2.1需要下载GParted软件

C++_回文串

目录 回文子串 最长回文子串 分割回文串 IV 分割回文串 II 最长回文子序列 让字符串成为回文串的最少插入次数 回文子串 647. 回文子串 思路&#xff0c;i j表示改范围内是否为回文串&#xff0c; ②倒着遍历是为了取出dp[i 1][j - 1] ③i j 只有一对&#xff0c;不会重复…

harmonyOS简介及背景

harmonyOS的场景模式18n: 1&#xff08;入口手机&#xff09;8&#xff08;电脑、VR、手环、iPad、智慧屏、&#xff09;–wifi—n(车载、智能家居等所有)harmonyOS不需要考虑软硬件的差异&#xff0c;是一个兼容N种的超级终端harmonyOS干了两件事&#xff1a; &#xff08;1&a…

施工升降机AI数人数识别摄像机

施工现场作为一个复杂的工作环境&#xff0c;在施工过程中通常会有大量的人员出入&#xff0c;为了确保施工安全和管理效率&#xff0c;近年来施工升降机AI数人数识别摄像机应运而生。 这种摄像机依靠先进的人工智能技术和摄像头设备&#xff0c;能够实时监测和识别施工升降机内…

AIGC——ComfyUI工作流搭建、导入与常用工作流下载

工作流 ComfyUI工作流是一个基于图形节点编辑器的工作流程&#xff0c;通过拖拽各种节点到画布上&#xff0c;连接节点之间的关系&#xff0c;构建从加载模型到生成图像的流程。每个节点代表一个与Stable Diffusion相关的模型或功能&#xff0c;节点之间通过连线传递图片信息。…

2390.从字符串中移除星号

题目&#xff1a;给你一个包含若干星号 * 的字符串 s 。 在一步操作中&#xff0c;你可以&#xff1a; 选中 s 中的一个星号。移除星号 左侧 最近的那个 非星号 字符&#xff0c;并移除该星号自身。 返回移除 所有 星号之后的字符串。 注意&#xff1a; 生成的输入保证总是…

如何对静态IP进行测试?静态IP有什么优点?

随着互联网的普及&#xff0c;越来越多的人开始使用动态IP进行上网。但是在某些情况下&#xff0c;我们可能需要使用静态IP进行测试或特定的网络设置。本文将介绍如何获取静态IP进行测试以及静态IP的优点。 一、如何获取静态IP进行测试&#xff1f; 1.联系ISP&#xff08;Int…

【JS】数组查重

码 /*** 数组查重* param {Array} arr 查重的数组* returns Array 返回不重复的数组 */ const noReArr arr > [...new Set(arr)]const a [12,12,3,4] console.log( noReArr(a) );效果图

031—pandas 读取解析实验室数据至DataFrame

前言 某个科研实验室在进行一项物理实现&#xff0c;实验仪器会输出一个 txt 文本的数据&#xff0c;研究人员需要从这个文本中将数据结构化才能进行进行统计分析。 在为个解析和分析过程中&#xff0c;他们选择了 Python 的 pandas 库来完成这些操作。我们今天来完成这这个 t…

使用AOP拦截全局请求并校验请求参数

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

【数据结构】猛猛干11道链表OJ(未完待续ing)

前言知识点 链表的调试技巧 int main() {struct ListNode* n1(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3(struct ListNode*)malloc(sizeof(struc…

蓝桥杯 2023 省B 飞机降落

首先&#xff0c;这题要求的数据量比较少&#xff0c;我们可以考虑考虑暴力解法。 这题可能难在很多情况的考虑&#xff0c;比如说&#xff1a; 现在时间是10&#xff0c;有个飞机20才到&#xff0c;我们是可以干等10分钟。 #include <iostream> #include <…