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

今日算法(带回文问题的回溯)

一、题目描述

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

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

示例 2输入:s = "a"输出:[["a"]]

示例 3输入:s = "aaa"输出:

[ ["a","a","a"], ["a","aa"], ["aa","a"], ["aaa"] ]

二、解法:纯回溯法(最易懂版本)

核心思路(一句话)

在字符串的空隙里尝试 “切一刀”,只要切出来的子串是回文,就继续往下切;直到切完整个字符串,就记录一种方案。


回溯三要素(必背)

  1. 选择:从当前位置开始,截取一段子串
  2. 限制:截取的子串必须是回文
  3. 结束:截取到字符串末尾,记录答案

三、完整代码(C++)

#include <vector> #include <string> using namespace std; class Solution { public: vector<vector<string>> partition(string s) { vector<vector<string>> result; // 存放最终所有答案 vector<string> path; // 存放当前正在分割的方案 backtrack(s, 0, path, result); return result; } private: // 回溯函数 // start: 从哪个下标开始分割 void backtrack(const string& s, int start, vector<string>& path, vector<vector<string>>& result) { // 1. 终止条件:已经分割到字符串末尾 → 记录答案 if (start == s.size()) { result.push_back(path); return; } // 2. 尝试所有可能的分割位置:从 start 开始,到 i 结束 for (int i = start; i < s.size(); ++i) { // 判断 s[start ... i] 是否是回文 if (isPalindrome(s, start, i)) { // 是回文 → 加入当前路径 path.push_back(s.substr(start, i - start + 1)); // 3. 递归:继续分割下一段 backtrack(s, i + 1, path, result); // 4. 回溯:撤销选择 path.pop_back(); } } } // 判断 s[left ... right] 是否是回文串 bool isPalindrome(const string& s, int left, int right) { while (left < right) { if (s[left] != s[right]) return false; left++; right--; } return true; } };

四、代码逐行解释(博客重点)

1. 主函数

backtrack(s, 0, path, result);
  • 从下标0开始分割
  • path记录当前分割方案
  • result收集所有合法答案

2. 终止条件

if (start == s.size())

表示已经把整个字符串分割完成,此时path就是一个合法方案,存入结果。

3. 循环尝试所有分割点

for (int i = start; i < s.size(); i++)
  • start:本次分割的起点
  • i:本次分割的终点
  • 截取子串:s[start ... i]

4. 只选择回文子串

if (isPalindrome(s, start, i))

只有子串是回文,才继续递归。

5. 回溯核心

path.push_back(...) backtrack(...) path.pop_back();
  • 先选
  • 再递归
  • 最后撤销选择,尝试下一种分割方式

五、案例 1:s = "aab" 完整推演(最经典)

字符串:a a b下标:0 1 2

第一层:start = 0

尝试分割:

  • [0,0] = "a"✅ 回文
  • [0,1] = "aa"✅ 回文
  • [0,2] = "aab"❌ 不是回文

分支 1:选 "a" → start = 1

第二层:start = 1

  • [1,1] = "a"✅ 回文 → start = 2
    • [2,2] = "b"✅ 回文 → start = 3(结束) → 得到方案:["a","a","b"]

分支 2:选 "aa" → start = 2

第二层:start = 2

  • [2,2] = "b"✅ 回文 → start = 3(结束) → 得到方案:["aa","b"]

最终结果

plaintext

[["a","a","b"], ["aa","b"]]

六、案例 2:s = "aaa" 推演(帮你彻底吃透)

所有可能分割:

  1. a | a | a
  2. a | aa
  3. aa | a
  4. aaa

回溯过程

  1. start=0 选a→ start=1 选a→ start=2 选a
  2. start=0 选a→ start=1 选aa
  3. start=0 选aa→ start=2 选a
  4. start=0 选aaa

最终输出 4 种方案。


七、案例 3:s = "ab"

  • 尝试[0,0] = "a"→ 剩下[1,1] = "b"→ 得到["a","b"]
  • 尝试[0,1] = "ab"❌ 不是回文结果:[["a","b"]]

八、回溯法为什么正确?

  1. 不重不漏:枚举所有合法分割点
  2. 剪枝:不是回文就直接跳过,不递归
  3. 结构清晰:标准回溯模板,面试必背

九、博客总结

  • 分割回文串是一道经典回溯题
  • 核心:枚举切割点 + 判断回文
  • 模板:选择 → 递归 → 撤销选择
  • 终止条件:切割到字符串末尾
  • 判断回文使用双指针即可
http://www.jsqmd.com/news/899165/

相关文章:

  • 戴森球计划8000+工厂蓝图终极指南:快速打造高效星际帝国
  • 告别RealVNC:在Ubuntu 20.04/22.04上快速搭建TigerVNC或x11vnc服务端(附防火墙配置)
  • ChatGPT辅助撰写IT技术文档:提升事故报告、操作手册与SOP效率
  • 【ChatGPT音乐理论解码指南】:20年作曲教授亲授——用AI精准解析调式、和声进行与曲式结构的5大认知盲区
  • 省钱又提效!大模型Token优化与减少使用技巧全指南
  • 田利健导演团队倾力护航《沿着边境看中国》第三季:融合真人秀元素,以匠心铸就边境新篇章
  • 2026程序员自学指南:国内口碑最好的三大编程实战网站,大厂面试刷题全靠它
  • py之某website之music搜索接口(某易版本)
  • 工业通信协议繁杂,设备接入困难?万德高科边缘计算网关来救场
  • 5G网络切片技术详解:从NFV/O-RAN架构到3GPP标准演进
  • 40VIN/VOUT,1.6A,XZ5130,升压LED恒流驱动芯片
  • Docker HUB Harbor 背后的镜像怎么存储的?存到哪里了?文件数据结构 底层存放方式
  • ContextCapture Master 倾斜摄影测量实景三维建模技术
  • 工业增强现实在智能船厂的应用实践:雾计算架构与AR性能评估
  • 网站对AI隐身?解析AEO挑战与RAG技术下的可见性策略
  • 2026年科里奥利质量流量计国产品牌排名:五家优选深度解析 - 科技焦点
  • 大语言模型效率优化实战:从量化、LoRA到推理部署的完整指南
  • EM68C16CWQG-25H DDR2 SDRAM芯片功能描述与操作逻辑
  • DownKyi:三步掌握B站高清视频下载的终极方案
  • 上百台服务器手动装Nginx?用Ansible Playbook一条命令搞定批量部署
  • py每日spider案例之某pan资源搜索接口(无加密)
  • OPC 产业学院适合什么专业的大学生?
  • ChatGPT导出Word怎么做?Chat2File 安装与使用教程
  • RH850 SPI实战:从FIFO模式到异步中断,如何让你的嵌入式通信又快又省CPU
  • 在vmware上面弄了个ubuntu,用ip addr查看ip,发现没ip
  • 2026年石化LNG领域质量流量计厂家推荐:五家优选深度解析 - 科技焦点
  • TaskbarX:3分钟让你的Windows任务栏图标居中,体验macOS般的优雅
  • 2026年广州钢结构开顶柜出口,这三点让你少走弯路
  • 养老护理行业数字化转型:技术架构与实现路径分析
  • 杭州企业招人,别再忽略背调这道关