当前位置: 首页 > 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.zskr.cn/news/1407337.html

相关文章:

  • 【ChatGPT音乐理论解码指南】:20年作曲教授亲授——用AI精准解析调式、和声进行与曲式结构的5大认知盲区
  • 2026程序员自学指南:国内口碑最好的三大编程实战网站,大厂面试刷题全靠它
  • 大语言模型效率优化实战:从量化、LoRA到推理部署的完整指南
  • OPC 产业学院适合什么专业的大学生?
  • ContextCapture Master 倾斜摄影测量实景三维建模技术
  • 在vmware上面弄了个ubuntu,用ip addr查看ip,发现没ip
  • TaskbarX:3分钟让你的Windows任务栏图标居中,体验macOS般的优雅
  • 养老护理行业数字化转型:技术架构与实现路径分析
  • 为Claude Code配置稳定可靠的Taotoken后端接入点
  • 《AI智能体时代,大学生如何提升竞争力?》
  • 一个AI从业者的持续学习法:每年考一个进阶认证当锚点
  • 5G网络切片技术详解:从NFV/O-RAN架构到3GPP标准演进
  • UE5官方文档(第一人称射击游戏教程)解读 第十章
  • 无人机辅助近场RIS物理层密钥生成:MRF方案与AI协调实践
  • HermesAgent用户指南如何配置Taotoken作为自定义模型提供商
  • 长期使用Taotoken Token Plan套餐的成本节约效果观察
  • ESXI 内网环境离线安装群晖NAS
  • 2026年电线电缆品牌推荐:珠江电缆优势深度解析与联系指南! - 资讯快报
  • ChatGPT写JD真的靠谱吗?一线大厂HR总监实测127份JD后,给出这5条铁律
  • 从曼哈顿图到临床解读:手把手教你用GATK和R完成GWAS分析并看懂结果
  • 从零到一:基于涂鸦Wi-Fi模组的智能红外遥控器DIY全攻略
  • 终极免费方案:一键突破百度网盘Mac版下载限制的完整指南
  • 2026 海南封关红利凸显,进出口贸易热度飙升!合规代办服务精选指南 - 资讯纵览
  • k8s入门-3
  • 学术写作提质新思路:paperxie 毕业论文 AI 创作功能实操使用解析
  • 如何快速掌握C++游戏开发:基于Cocos2d-x的植物大战僵尸完整实战指南
  • Cache主存地址映射实战:从课后题到三种映射方式的地址格式设计
  • MCP博客园工具集成测试v2
  • 2026年驱蚊雾森系统排名:最新权威排名与专业指南。 - 资讯快报
  • 建筑领域“混凝土配合比智能优化”高价值专利案例:一种钢纤维混凝土抗压强度预测方法