news 2026/4/17 14:40:54

回溯算法--分割回文串

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
回溯算法--分割回文串

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回 s 所有可能的分割方案。

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

难点

本题的难点在于

  1. 怎么理解或者实现分割这个概念。
  2. 怎么分割的字符串怎么定义。

分割这个问题类似于组合问题,定义一个startIndex,startIndex指向那个字符就是分割的位置。

for(int i = startIndex; i < s.size(); i ++), 在对字符串进行横向遍历的时候,statrIndex 到 i 的长度不就是分割字符串。

思路

定义参数

vector<vector<string>> result; vector<string> path; // 核心的回溯函数 // s: 输入的原始字符串 // startIndex: 当前遍历的起始位置 void backtracking(const string& s, int startIndex)

递归结束条件

当分割到最后一个字符时,说明已经分割完毕,并且一定有满足条件的path,因为每个每个单个字母一定是回文串。

if(startIndex == s.size()){ // 将当前构造的分割方案 (path) 添加到最终结果 (result) 中 result.push_back(path); return; }

单层递归逻辑

首先判断分割的字符串是否为回文串,如果是,则压入path。如果不是则跳过,继续考察更长的子串。

当考察到回文串的时候,才会继续向下递归。

// 单层搜索逻辑:从 startIndex 开始,向后遍历字符串 for(int i = startIndex; i < s.size(); i ++){ // 判断从 startIndex 到 i 的子串是否是回文串 if(isPalindrome(s, startIndex, i)){ // 如果是回文串,将其加入到当前路径 (path) 中 // s.substr(startIndex, i - startIndex + 1) 截取了从 startIndex 开始,长度为 i - startIndex + 1 的子串 path.push_back(s.substr(startIndex, i - startIndex + 1)); }else{ // 如果不是回文串,则跳过,继续考察更长的子串 continue; } // 递归:进入下一层决策,起始位置变为 i + 1 backtracking(s, i + 1); // 回溯:撤销当前层的选择,将刚刚加入的子串弹出,以便探索其他可能性 path.pop_back(); }

代码

#include<iostream> #include<vector> using namespace std; // 解题的核心类 class Solution { private: vector<vector<string>> result; vector<string> path; // 核心的回溯函数 // s: 输入的原始字符串 // startIndex: 当前遍历的起始位置 void backtracking(const string& s, int startIndex){ // 基本情况(终止条件):如果起始位置已经等于字符串长度, // 说明我们已经找到了一个完整的分割方案 if(startIndex == s.size()){ // 将当前构造的分割方案 (path) 添加到最终结果 (result) 中 result.push_back(path); return; } // 单层搜索逻辑:从 startIndex 开始,向后遍历字符串 for(int i = startIndex; i < s.size(); i ++){ // 判断从 startIndex 到 i 的子串是否是回文串 if(isPalindrome(s, startIndex, i)){ // 如果是回文串,将其加入到当前路径 (path) 中 // s.substr(startIndex, i - startIndex + 1) 截取了从 startIndex 开始,长度为 i - startIndex + 1 的子串 path.push_back(s.substr(startIndex, i - startIndex + 1)); }else{ // 如果不是回文串,则跳过,继续考察更长的子串 continue; } // 递归:进入下一层决策,起始位置变为 i + 1 backtracking(s, i + 1); // 回溯:撤销当前层的选择,将刚刚加入的子串弹出,以便探索其他可能性 path.pop_back(); } } bool isPalindrome(const string& s, int i, int j){ while(i <= j){ if(s[i] != s[j]){ return false; }else{ i ++; j --; } } return true; } public: vector<vector<string>> partition(string s) { result.clear(); path.clear(); backtracking(s, 0); return result; } }; int main(){ Solution S; string s = "abcd"; vector<vector<string>> result = S.partition(s); for(auto row : result){ for(auto cols : row){ cout << cols << " "; // 打印子串 } cout << endl; // 每打印完一种方案后换行 } return 0; // 程序正常退出 }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 8:47:36

Python 全面深入解析:从入门到精通

Python 全面深入解析&#xff1a;从入门到精通第一部分&#xff1a;Python 语言概述与哲学1.1 Python 的诞生与发展Python 由吉多范罗苏姆&#xff08;Guido van Rossum&#xff09;于1989年圣诞节期间在荷兰创建&#xff0c;最初作为 ABC 语言的替代品。1991年&#xff0c;Pyt…

作者头像 李华
网站建设 2026/4/18 9:34:50

一个完整的 Web 请求到底发生了什么

一、从输入一个网址开始 当我们在浏览器输入一个网址&#xff0c;然后按下回车&#xff0c;接下来浏览器显示了页面。网速好的话这之间可能就一秒&#xff0c;但在这一秒内到底发生了什么&#xff1f; 本文主要内容是试图记录一个完整 Web 请求的详细过程&#xff0c;从用户在…

作者头像 李华
网站建设 2026/4/17 18:15:44

JAVA中如何利用JSP实现大文件上传的验证机制?

大文件上传下载系统开发指南 项目概述 老哥&#xff0c;你这个需求可真是够硬核的&#xff01;20G文件上传、文件夹层级保留、断点续传、加密传输存储&#xff0c;还要兼容IE8&#xff0c;预算才100块…这活儿不简单啊&#xff01;不过既然你找到我了&#xff0c;咱们就一起啃…

作者头像 李华
网站建设 2026/4/17 8:47:40

【AI黑科技】告别“金鱼记忆“!这5个开源项目让你的AI Agent从此“过目不忘“,小白也能轻松上手!

**Agent 的“聪明”&#xff0c;一半靠 LLM&#xff0c;一半靠记忆系统。**目前开源圈里&#xff0c;向量数据库百花齐放&#xff0c;但真正能打的也就那么几个。下面这几个开源项目&#xff0c;就是专门为解决这些问题而生的——它们让 Agent 真正拥有了“长期记忆 自我进化”…

作者头像 李华
网站建设 2026/4/17 12:18:30

Python基础七:条件判断与循环判断

一、条件判断 &#xff08;一&#xff09;基本语法 1.if语句 if 要判断的条件:条件成立时要做的事情1条件成立时要做的事情2等等# if语句 # 代码书写时&#xff0c;冒号为英文符号&#xff0c;每个条件下的代码块统一比条件向后缩进一个制表键&#xff08;四个空格的大小&#…

作者头像 李华
网站建设 2026/4/17 8:47:48

后端springboot框架入门学习--第一篇

Spring Boot 是一个非常流行且强大的 Java 后端开发框架&#xff0c;它的核心目标是简化基于 Spring 框架应用的初始搭建和开发过程&#xff0c;可以把它理解为 Spring 框架的一个“增强套件”或“快速启动包”。核心组成部分&#xff1a;启动器、自动配置、外部化配置、Spring…

作者头像 李华