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

【Leetcode hot 100】131.分割回文串

问题链接

131.分割回文串

问题描述

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

示例 1:

输入:s = “aab”
输出:[[“a”,“a”,“b”],[“aa”,“b”]]

示例 2:

输入:s = “a”
输出:[[“a”]]

提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

问题解答

方法一:基础回溯 + 双指针判断回文

思路解析

  1. 回溯框架:用path存储当前分割出的回文子串,用result存储所有有效分割方案;start为当前分割的起始索引(标记已处理完s[0..start-1],待处理s[start..n-1])。
  2. 终止条件:当start == s.length()时,说明已分割到字符串末尾,将path的拷贝加入result(避免引用修改)。
  3. 遍历与判断:从start开始遍历所有可能的结束索引i,用双指针判断s[start..i]是否为回文串。若为回文,则将子串加入path,递归处理start = i+1,最后回溯(移除path末尾元素)。

代码实现

import java.util.ArrayList;
import java.util.List;class Solution {// 存储所有有效分割方案private List<List<String>> result = new ArrayList<>();// 存储当前分割的回文子串private List<String> path = new ArrayList<>();public List<List<String>> partition(String s) {// 从起始索引0开始回溯backtrack(s, 0);return result;}/*** 回溯函数* @param s 原始字符串* @param start 当前分割的起始索引*/private void backtrack(String s, int start) {// 终止条件:已分割到字符串末尾if (start == s.length()) {result.add(new ArrayList<>(path)); // 拷贝path,避免后续修改影响结果return;}// 遍历所有可能的结束索引i(从start到末尾)for (int i = start; i < s.length(); i++) {// 判断s[start..i]是否为回文串if (isPalindrome(s, start, i)) {// 若为回文,加入当前路径path.add(s.substring(start, i + 1)); // substring是[左闭右开),需i+1// 递归处理下一段(起始索引更新为i+1)backtrack(s, i + 1);// 回溯:移除最后一个元素,尝试其他分割方式path.remove(path.size() - 1);}}}/*** 双指针判断子串s[left..right]是否为回文串* @param s 原始字符串* @param left 子串左边界* @param right 子串右边界* @return 是回文串返回true,否则false*/private boolean isPalindrome(String s, int left, int right) {while (left < right) {// 左右指针字符不相等,不是回文if (s.charAt(left) != s.charAt(right)) {return false;}left++;right--;}return true;}
}

方法二:回溯 + 动态规划(DP)预处理回文

思路优化点
方法一中,每次判断回文串都用双指针扫描(时间O(n)),存在重复计算(如s[0..2]s[1..1]会重复判断s[1])。
通过DP预处理,提前计算出所有子串s[i..j]是否为回文串,后续判断可直接查DP数组(时间O(1)),降低时间复杂度。

具体步骤

  1. DP数组定义dp[i][j]表示子串s[i..j]是否为回文串(i <= j)。
  2. DP初始化
    • 单个字符(i == j):dp[i][i] = true(必然是回文)。
    • 两个字符(j = i+1):dp[i][j] = (s.charAt(i) == s.charAt(j))(字符相等则为回文)。
  3. DP填充:对于长度>2的子串(j - i > 1),需满足两个条件:
    • 子串首尾字符相等(s.charAt(i) == s.charAt(j))。
    • 中间子串s[i+1..j-1]是回文(dp[i+1][j-1] = true)。
    • 填充顺序:需从下往上、从左往右遍历i(因dp[i][j]依赖dp[i+1][j-1],需先计算i+1层)。
  4. 回溯逻辑:与方法一一致,仅将isPalindrome判断替换为dp[start][i]

代码实现

import java.util.ArrayList;
import java.util.List;class Solution {private List<List<String>> result = new ArrayList<>();private List<String> path = new ArrayList<>();// DP数组:dp[i][j]表示s[i..j]是否为回文串private boolean[][] dp;public List<List<String>> partition(String s) {int n = s.length();// 初始化DP数组(n x n)dp = new boolean[n][n];// 1. 填充DP数组:单个字符的回文for (int i = 0; i < n; i++) {dp[i][i] = true;}// 2. 填充DP数组:两个字符的回文for (int i = 0; i < n - 1; i++) {dp[i][i + 1] = (s.charAt(i) == s.charAt(i + 1));}// 3. 填充DP数组:长度>2的子串(从下往上、从左往右遍历i)for (int i = n - 3; i >= 0; i--) { // i从倒数第3个字符开始(保证j=i+2存在)for (int j = i + 2; j < n; j++) { // j从i+2开始(长度>=3)dp[i][j] = (s.charAt(i) == s.charAt(j)) && dp[i + 1][j - 1];}}// 开始回溯backtrack(s, 0);return result;}// 回溯函数(与方法一一致,仅回文判断替换为DP数组)private void backtrack(String s, int start) {if (start == s.length()) {result.add(new ArrayList<>(path));return;}for (int i = start; i < s.length(); i++) {// 直接查DP数组判断回文(O(1)时间)if (dp[start][i]) {path.add(s.substring(start, i + 1));backtrack(s, i + 1);path.remove(path.size() - 1);}}}
}

复杂度分析

解法时间复杂度空间复杂度
方法一(基础)O(n × 2ⁿ)O(n)
方法二(DP优化)O(n² + n × 2ⁿ)O(n²)
  • 时间:两种解法的核心都是枚举2ⁿ种分割方式(每个位置有“分割”或“不分割”两种选择),方法一判断回文需O(n),方法二预处理O(n²)后判断回文O(1),整体优化后更高效。
  • 空间:方法一的空间来自递归栈(深度n)和path(长度n);方法二额外增加O(n²)的DP数组。
http://www.dtcms.com/a/445907.html

相关文章:

  • ARM - GCC - 建立自己的命令行编译环境
  • Nginx限流配置
  • 大岭山做网站九亭做网站公司
  • 微软宣布 Windows 11 v25H2 GA
  • Burp Suite模拟器抓包全攻略
  • 佛山营销型网站定制绿色企业网站源码
  • Qt 5.14.2+Mysql5.7 64位开发环境下无法连接数据库
  • 【Python】
  • [特殊字符]ui设计公司灵感备忘录 | 网格布局 UI 收集
  • Base UI:一款极简主义的「无样式」组件库
  • MySQL 运维知识点(十六)---- 读写分离
  • 网站建设生存期模型希音电商网站
  • 济南网站建设培训班永久免费网站建设
  • 高层次综合报告分析-vivado hls第四章
  • Go语言中的Zap日志库
  • Linux网络编程——UdpServer
  • Daily算法刷题【面试经典150题-3️⃣】
  • MybatisPlus和pagehelper分页冲突—关于jsqlparser、pagehelper、MybatisPlus三者的版本兼容问题
  • R 数组:深入解析与高效使用
  • 缩点学习笔记
  • Go基础:用Go语言操作MongoDB详解
  • 第六章:适配器模式 - 接口转换的艺术大师
  • ARM环境日志系统的简单设计思路
  • 网站名称推荐大气聚财的公司名字
  • 【JVM】——实战篇
  • 那里有正规网站开发培训学校个人网站是怎么样的
  • 高端网站设计简介推荐外贸网站建设的公司
  • asp.net 网站安装工商核名在哪个网站
  • 基于websocket的多用户网页五子棋(五)
  • 【图像处理基石】什么是全景视觉?