Backtracking algorithm梳理

article/2025/9/23 6:29:14

回溯法简介
注意下面这句话
由于回溯通常结果集都记录在回溯树的路径上,因此如果不进行撤销操作, 则可能在回溯后状态不正确导致结果有差异, 因此需要在递归到底部往上冒泡的时候进行撤销状态。
如果你每次递归的过程都拷贝了一份数据,那么就不需要撤销加粗样式状态,相对地空间复杂度会有所增加

回溯法都可以抽象为树形结构,其实每一层都代表了一个for循环
以下面题为例,k=2时是两个for循环,k=50是50个for循环,后者写不出来,但是回溯能够写得出来。

77. 组合

给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
输入: n = 4, k = 2
输出:
[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4]]
在这里插入图片描述
剪枝优化
在这里插入图片描述
在这里插入图片描述

class Solution {
public:vector<vector<int>> combine(int n, int k) {vector< int > temp;dfs(temp, n, 1, k);return ret;}void dfs(vector<int>& v, int n, int nowIndex, int k){if (v.size() == k){ret.emplace_back(v);return;}else if (nowIndex > n){return;}//加入路径,遍历,消除关系for (int i = nowIndex; i <= n&& n-i+1 >= (k-v.size()); i++){v.emplace_back(nowIndex);dfs(v, n, ++nowIndex, k);v.pop_back();        }}
public:vector<vector<int>>ret;
};

216. 组合总和 III

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

在这里插入图片描述
每个for循环也是从开始索引遍历剩下的数

class Solution {
public:vector<vector<int>> combinationSum3(int k, int n) {vector<int>temp;dfs(n,k,1,temp);return ret;}void dfs(int target,int k,int startindex,vector<int>&temp){//找到目标值为target的 k个数//终止条件 1、当前为k个值了,并且目标值为0 即成功加入最后集合中//2、非正常结束 超过k个值了或者目标值小于0了,错误退出,直接returnif(temp.size() == k && target == 0){ret.emplace_back(temp);return;}//这里的等于是上面没有被挑选的else if(temp.size() >= k || target <= 0) return ;//正常逻辑,加入,执行dfs,取消加入 for(int i = startindex; i <= 9 || 10-i > k-temp.size() ; i++){temp.emplace_back(i);dfs(target-i,k,i+1,temp);temp.pop_back();}}
public:vector<vector<int>> ret;
};

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]

如果用for循环怎么做
对于给的每个数进行循环
这里训练的是string的一些使用方法
在这里插入图片描述

39.组合总和

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

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

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但还有种方法,要么加本元素,要么开始下一个元素(用这种方法)
在这里插入图片描述

class Solution {
public:vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<int>temp;dfs(candidates, target, 0, temp);return ret;}void dfs(vector<int>& candidates, int target, int startIndex, vector<int>&temp){//1、返回,target = 0if (target == 0){ret.emplace_back(temp);return;}else if (startIndex > candidates.size() - 1 || target < 0) return;//1、继续用当前值temp.emplace_back(candidates[startIndex]);dfs(candidates, target-candidates[startIndex], startIndex, temp);temp.pop_back();//2、用下一个值dfs(candidates, target, startIndex + 1, temp);}
public:vector<vector<int>> ret;
};

40. 组合总和 II

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

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

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

在这里插入图片描述
加上如下重复的判断,会出错,因为是从左向右判断的(有的编译器可能是相反的),因此需要将i>0放大前面。

 if (candidates[i] == candidates[i - 1] && i > 0)continue;

放到前面来

if (i > 0 &&candidates[i] == candidates[i - 1])continue;

但这样会出错,有的时候可能是重复的两个都加上,比如 1 1 5,这样加上判断后会省略当前的元素

如果加上used标记是否已经使用
在这里插入图片描述

或者不用used,直接用同一层的移动
在这里插入图片描述

二、切割问题

切割问题,切了以后两边就没有关系了
针对切割问题,可以通过for来的,就像下面图一样,第一层for循环,我可以选择在g切,也可以在goog处切,切了以后就没关系了,下次的递归是选择新的字符串的切割位置,也就是我切了以后,前边和后边就没有关系了,将前面加到容器里,这是产品。然后一直遍历,等到没地方切了,也就是切得位置到了最终位置,那么就是递归完成了,没有产品再往容器里放了
在这里插入图片描述

131. 分割回文串

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
google的[[“g”,“o”,“o”,“g”,“l”,“e”],[“g”,“oo”,“g”,“l”,“e”],[“goog”,“l”,“e”]]
在这里插入图片描述
在这里插入图片描述

class Solution {
public:vector<vector<string>> partition(string s) {//对于n判断后面的vector<string> cur;dfs(s, cur, 0);return ret;}//1、需要有个s,线回文串缓存,startIndexvoid dfs(const string& s, vector<string>&cur,int startIndex){if (startIndex > s.size()-1){ret.emplace_back(cur);return;}/** 1、对于每一个加入startindex,判断加上这个是否是回文,是回文则开辟分支,让其进行下一个for循环* 2、不是则绕过*/for (int i = startIndex; i < s.size(); i++)//在这层for循环里寻找一切可以切割的位置,然后切下去调用新的切割 {if (isHW(s, startIndex, i)){cur.emplace_back(s.substr(startIndex,i - startIndex + 1));dfs(s, cur, i+1);cur.pop_back();}}}bool isHW(const string &s,int Startindex,int Endindex){while (Startindex != Endindex && Startindex < Endindex){if (s[Startindex] != s[Endindex]){return false;}else {Startindex++;Endindex--;} }return true;}
public:vector<vector<string>> ret;};

93. 复原 IP 地址

在这里插入图片描述
终止条件为段数大于4,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、子集问题

78. 子集

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

90. 子集 II

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

和上题一样,只不过要去除重复,本层不能有相同的,不同层的可以
在这里插入图片描述

491. 递增子序列

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

在这里插入图片描述
在这里插入图片描述
在每执行一次dfs时都加入ret里面

46.全排列

在这里插入图片描述
在这里插入图片描述
虽然这样看上去是层次一样的,但是用used的话,是每个分支弄完才会到另一个分支上,这个dfs是深度遍历的
在这里插入图片描述

47.全排列 II

在这里插入图片描述
同一层回溯,前面用了,后面就不能用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


http://chatgpt.dhexx.cn/article/SDU7J9kK.shtml

相关文章

ARM backtrace 实战分析

记录一下arm backtrace 分析过程 前言 嵌入式开发中&#xff0c;如果发生异常如内存访问越界等情况&#xff0c;有时会非常难debug到底是哪里出错&#xff0c;近来看了一下back trace回溯的功能及实现,在这里做个笔记。 backtrace就是回溯堆栈&#xff0c;简单的说就是可以列…

backtrack 5 r3

1.BT5默认用户名:root.密码:toor(公司是yeslabccies) 2.进入图形化界面命令:startx 3.更改密码&#xff1a;sudo passwd root 扫描工具 第一部分网络配置&#xff1a; 4.网络配置文件有两个&#xff1a; /etc/network/interfaces 和 /etc/resolv.conf 前一个存放网卡接口…

backtrack3安装使用教程

一、准备篇 1、一个有可破解无线信号的环境。如我在家随便搜索出来的信号。 2、带无线网卡的电脑一台&#xff08;笔记本台式机均可&#xff0c;只要无线网卡兼容BT3&#xff09;&#xff0c;我用的是三星R467的上网本。  3、2G以上优盘一个&#xff08;我用的是2G的&#x…

安装BackTrack5 R3

最近买了本《Python绝技》&#xff0c;里面的很多实例都是在BackTrack系统中运行的。初次接触BackTrack系统&#xff0c;才知道它是一套专业的计算机安全检测的Linux操作系统&#xff0c;内部集成了200多种安全检查工具。虽然现在BackTrack已经被Kali Linux所代替&#xff0c;不…

BackTrack5(BT5)各版本下载

BT5R3(最新版本)http://www.nigesb.com/backtrack-5-r3-released.html BT5R2 KDE版32位&#xff1a; http://ftp.halifax.rwth-aachen.de/backtrack/BT5R2-KDE-32.iso GNOME32位&#xff1a;http://ftp.halifax.rwth-aachen.de/backtrack/BT5R2-GNOME-32.iso BT5R1 KDE版32位…

小白使用backtrack5

在此先感谢飞飞老师录制的教学视频 在这几天的了解中知道了这样一个过程 linux–>Debian–>Ubuntu–>backtrack–>kali 可能理解有点片面&#xff0c;但是可以让我了解到linux系统是基础&#xff0c;而且linux的内核大部分都是用C写的&#xff0c;部分是汇编语言…

虚拟机安装BackTrack 5 的教程详解!

废话不多说&#xff0c;直接上教程&#xff01;如在安装过程中有些步骤界面没显示&#xff0c;即直接下一步即可。 打开虚拟机&#xff0c;新建虚拟机 选择自定义安装 选择你的映像文件&#xff0c;点击下一步 这里要注意了&#xff0c;系统选择Linux&#xff0c;版本选择U…

struts2漏洞升级至2.5.30额外补充

由于部分老项目需要还在使用struts2框架&#xff0c;由于最新发布struts2漏洞&#xff0c;需要将其版本升级至struts2.5.30&#xff0c;同步还有其他依赖和配置需要调整&#xff0c;大概可参考这个文章&#xff1a; struts升级至2.5.26遇到的各种bug及解决方案_谷同学的博客-C…

linux struts2漏洞,Struts2漏洞分析,漏洞波及全系版本

Struts漏洞分析 Apache Struts团队已经发布了Struts 2.3.15.1安全更新版本。在Struts2.3.15.1版本之前&#xff0c;存在着严重的安全漏洞&#xff0c;如果现在一些比较大的网站是用JAVA做的&#xff0c;没有把版本升级&#xff0c;还用的是Strtus2.3.15.1版本之前的话&#xff…

渗透知识-Struts2漏洞

Struts2漏洞利用实例 如果存在struts2漏洞的站&#xff0c;administrator权限&#xff0c;但是无法加管理组&#xff0c;内网&#xff0c;shell访问500. 1.struts2 漏洞原理&#xff1a;struts2是一个框架&#xff0c;他在处理action的时候&#xff0c;调用底层的getter/sette…

Struts2 远程代码执行漏洞复现(附Struts2漏洞检测工具)

0x00 Struts2 简介 Struts2 是 Apache 软件组织推出的一个相当强大的 Java Web 开源框架&#xff0c;本质上相当于一个 servlet。Struts2 基于 MVC 架构&#xff0c;框架结构清晰。通常作为控制器&#xff08;Controller&#xff09;来建立模型与视图的数据交互&#xff0c;用…

Struts2漏洞利用原理

概述: Struts2是apache项目下的一个web 框架,目前web框架中非常流行的都是mvc设计模式、经典例子例如:python的Django、Flask;java的ssm等。因为使用MVC设计模式,所以在框架内部处理用户数据流参数的事后就不可避免的存在数据在不同层次流转的问题。struts2作为java的一款成…

Struts2漏洞 - Struts2-015 Struts2-016 Struts2-045

文章目录 Struts2简介Struts2历史漏洞Struts2历史漏洞发现Struts2框架识别 Struts2历史漏洞利用Struts2-015漏洞简介影响范围环境搭建漏洞复现 Struts2-016漏洞简介影响范围环境搭建漏洞复现 Struts2-045漏洞简介影响范围环境搭建漏洞复现 Struts2简介 Apache Struts是美国阿帕…

Struts2漏洞S2-005复现

1.漏洞描述 s2-005漏洞的起源源于S2-003(受影响版本: 低于Struts 2.0.12)&#xff0c;struts2会将http的每个参数名解析为OGNL语句执行(可理解为java代码)。OGNL表达式通过#来访问struts的对象&#xff0c;struts框架通过过滤#字符防止安全问题&#xff0c;然而通过unicode编码…

Struts2 漏洞集合

Struts2 漏洞集合 总结了一部分 Strtus2 漏洞&#xff0c;虽然现在这部分的漏洞很少了&#xff0c;但也是学习的一部分&#xff0c;收集的并不全面&#xff0c;后续会做补充。 漏洞环境搭建可以使用在线的 Vulfocus &#xff0c;或者使用docker部署 S2-001 &#xff08;CVE-…

Vulhub靶场之struts2漏洞复现

简介 struts2漏洞中属s2系列杀伤力最大&#xff0c;可以造成远程命令执行漏洞。 Apache Struts2框架是一个用于开发Java EE网络应用程序的Web框架。Apache Struts于2020年12月08日披露 S2-061 Struts 远程代码执行漏洞(CVE-2020-17530)&#xff0c;在使用某些tag等情况下可能…

java struts2 漏洞_Struts2漏洞利用

Struts漏洞合集 Struts-S2-013漏洞利用 受影响版本 Struts 2.0.0 - Struts 2.3.14.1 漏洞利用 任意命令执行POC&#xff1a; ${(#_memberAccess["allowStaticMethodAccess"]true,#ajava.lang.RuntimegetRuntime().exec(id).getInputStream(),#bnew java.io.InputStre…

struts2漏洞监测_全版本struts2漏洞练习

docker中有struts2全版本的漏洞平台 1、首先在docker中进行下载&#xff1a; # docker pull 2d8ru/struts2 2、其次运行&#xff1a;(48729为物理机的端口&#xff0c;可随意指定) # docker run --name struts2 -p48729:8080 -d 2d8ru/struts2 3、下载struts2漏洞扫描工具&…

Struts2漏洞复现

一. S2-016复现 打开测试靶场&#xff0c;测试该网站存在index.action路径 漏洞原理: 参数action的值redirect以及redirectAction没有正确过滤&#xff0c;导致ognl代码执行 测试POC&#xff1a; 2.1 /index.action?redirect:%25{3*4}2.2 /index.action?redirect:%…

java struts2 漏洞_Struts2漏洞简述

S2-005漏洞 S2-005是由于官方在修补S2-003不全面导致绕过补丁造成的。我们都知道访问Ognl的上下文对象必须要使用#符号&#xff0c;S2-003对#号进行过滤&#xff0c;但是没有考虑到unicode编码情况&#xff0c;导致\u0023或者8进制\43绕过。 S2-005则是绕过官方的安全配置(禁止…