当前位置: 首页 > news >正文

回溯.专题

一、入门回溯

二、子集型回溯

三、划分型回溯

核心思路:把分割线(逗号)看成是可以「选或不选」的东西,本质是子集型回溯。

Leetcode 131. 分割回文串

思路:枚举子串结束位置(同下一题93的回溯法二)

Code:

class Solution {
public:bool jdg(string s) {    // 判断是否是回文串int n = s.length();int i = 0, j = n - 1;while (i < j) {if (s[i] != s[j])   return false;i ++, j --;}return true;} vector<vector<string>> partition(string s) {vector<vector<string>>  res;vector<string>          tmp;int n = s.length();auto dfs = [&](this auto&& dfs, int i) -> void{if (i == n) {res.push_back(tmp);return;}for (int k = 1; k <= n; k ++) {if (i + k <= n && jdg(s.substr(i, k))){tmp.push_back(s.substr(i, k));dfs(i + k);tmp.pop_back();}   }};dfs(0);return res;}
};

Leetcode 93. 复原 IP 地址

思路一:三重循环枚举

         注意判断的时候额外关注一下前导零的判断。

class Solution {
public:vector<string> restoreIpAddresses(string s) {// 判断子串[i, j)是否合法auto jdg = [&](int i, int j) -> bool {// len <= 3 && 不能有前导零if (j - i > 3 || j - i > 1 && s[i] == '0')return false;   // 没有前导零才能用stoi->否则会自动筛掉前导0return stoi(s.substr(i, j - i)) <= 255; // 数字范围};int n = s.size();vector<string> res;for (int i = 1; i < n && jdg(0, i); i ++)for (int j = i + 1; j < n && jdg(i, j); j ++) for (int k = j + 1; k < n && jdg(j, k); k ++)if (jdg(k, n))res.push_back(s.substr(0,i)+'.'+s.substr(i,j-i)+'.'+s.substr(j,k-j)+'.'+s.substr(k));return res;}
};

思路二:回溯法 之 选或不选(是否分割)

class Solution {
public:vector<string> restoreIpAddresses(string s) {int n = s.size();vector<string> res;int path[4];    // path[i]表示第i段结束位置 + 1(右开区间)auto dfs = [&](this auto&& dfs, int i, int j, int ip_val) -> void {if (i == n)  {  // s 分割完毕if (j == 4) // 必须有4段{auto [a, b, c, _] = path;res.emplace_back(s.substr(0,a)+"."+s.substr(a,b-a)+"."+s.substr(b,c-b)+"."+s.substr(c));}return;}if (j == 4) return;// j==4的时候必须分割完毕,不能有剩余的字符(j从0开始的)// 手动str->int, 严格o(1)ip_val = ip_val * 10 + (s[i] - '0');if (ip_val > 255)   return; // 不合法// ①不分割,不以s[i]为这一段的结尾if (ip_val > 0) dfs(i + 1, j, ip_val);// ②分割 -> 以s[i]为这一段的结尾path[j] = i + 1;    // 记录下一段的开始位置dfs(i + 1, j + 1, 0);   // ipval清零};dfs(0, 0, 0);   return res;}
};

思路三:回溯法 之 (枚举子串右端点)

class Solution {
public:vector<string> restoreIpAddresses(string s) {int n = s.size();vector<string> res;string path[4];// 分割s[i]到s[n-i],当前从第j段开始(j从0开始)auto dfs = [&](this auto&& dfs, int i, int j) -> void{// 剪枝// 还剩下n-i个字符,需要分成4-j 段,每段至少1个字符,至多3个字符,所以4-j<=n-i <=(4-j)*3if (n - i < 4 - j || n - i > (4 - j) * 3)   return;if (i == n) {res.emplace_back(path[0]+'.'+path[1]+'.'+path[2]+'.'+path[3]);return;}// 子串左端点是i, 枚举子串的右端点rightint ip_val = 0;for (int right = i; right < n; right ++) {ip_val = ip_val * 10 + (s[right] - '0');if (ip_val > 255)   break;  // illegalpath[j] = s.substr(i, right - i + 1);   // 直接覆盖,无需恢复现场dfs(right + 1, j + 1);if (ip_val == 0)    break;  // 如果当前数是0,对于后续for都不合法(排除前导零)}};dfs(0, 0);return res;}
};

四、组合型回溯

五、排列型回溯

六、有重复元素的回溯

七、搜索

八、折半枚举

http://www.dtcms.com/a/393408.html

相关文章:

  • QML学习笔记(五)QML新手入门其三:使用Row和Colunm进行简单布局
  • 【视图功能11】视图权限控制与协作场景实践
  • YOLOv5至YOLOv12升级:交通标志识别系统的设计与实现(完整代码+界面+数据集项目)
  • 双指针算法案例:有序顺序表的交并差
  • syn和quote实现派生宏Builder
  • MQTT消息质量等级——QoS
  • 【OpenGL】shader 着色器
  • 给AI装上“眼睛”:Schema标记和技术性GEO实战部署
  • 中超-克雷桑破门 齐鲁德比泰山2-2遭海牛读秒绝平!
  • gitflow在公司的全流程
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘grpc’ 问题
  • C语言第17讲
  • 人机协同开发中的“深水炸弹”——指令上下文混淆
  • 朴素贝叶斯算法详解:原理、应用与实践
  • 强化学习的数学原理-02章 贝尔曼公式
  • C++:入门基础(2)
  • 数据架构章节考试考点及关系梳理
  • 用TRAE编程助手编写一个浏览器插件
  • 赋能工业未来:向成电子XC3576H工控主板多领域应用前景
  • Multi-Agent多智能体系统(三)
  • 【语法进阶】高级用法、贪婪与非贪婪
  • 15天见效的SEO优化方案
  • C语言基础【20】:指针7
  • IC 数字逻辑设计中的硬件算法 01 记
  • 《棒球运动联盟》国家级运动健将标准·棒球1号位
  • AAC 详解
  • 蚂蚁集团DIVER登顶BRIGHT榜首,开源多阶段推理检索范式
  • 2013/12 JLPT听力原文 问题四
  • 挑战与应对:轻量化 AI 算法的成长烦恼
  • FPGA基础 -- CDC(Clock Domain Crossing)实战教程