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

LeetCode第132题_分割回文串II

LeetCode 第132题:分割回文串 II

题目描述

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

返回符合要求的 最少分割次数

难度

困难

题目链接

点击在LeetCode中查看题目

示例

示例 1:

输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

示例 2:

输入:s = "a"
输出:0

示例 3:

输入:s = "ab"
输出:1

提示

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

解题思路

方法一:动态规划

这道题是"分割回文串"的进阶版,要求找到最少的分割次数,使得分割后的每个子串都是回文串。我们可以使用动态规划来解决这个问题。

关键点:

  • 使用动态规划预处理判断子串是否为回文串
  • 使用动态规划计算最少分割次数

具体步骤:

  1. 预处理判断子串是否为回文串
    • 定义isPalindrome[i][j]表示s[i…j]是否为回文串
    • 状态转移方程:isPalindrome[i][j] = (s[i] == s[j]) && (j - i <= 1 || isPalindrome[i+1][j-1])
  2. 计算最少分割次数
    • 定义dp[i]表示s[0…i]的最少分割次数
    • 初始化dp[i] = i(最坏情况下,每个字符都是一个回文串,需要i次分割)
    • 状态转移方程:
      • 如果s[0…i]是回文串,则dp[i] = 0(不需要分割)
      • 否则,遍历j从0到i-1,如果s[j+1…i]是回文串,则dp[i] = min(dp[i], dp[j] + 1)
  3. 返回dp[n-1],其中n是字符串的长度

时间复杂度:O(n2),其中n是字符串的长度。需要O(n2)的时间预处理回文串,以及O(n^2)的时间计算最少分割次数。
空间复杂度:O(n2),需要O(n2)的空间存储isPalindrome数组,以及O(n)的空间存储dp数组。

方法二:优化的动态规划

我们可以对方法一进行优化,减少空间复杂度。

关键点:

  • 使用中心扩展法判断回文串,避免使用O(n^2)的空间
  • 使用动态规划计算最少分割次数

具体步骤:

  1. 定义dp[i]表示s[0…i]的最少分割次数
  2. 初始化dp[i] = i(最坏情况下,每个字符都是一个回文串,需要i次分割)
  3. 对于每个位置i,以i为中心向两边扩展,找到所有以i为中心的回文串
    • 对于奇数长度的回文串,从i向两边扩展
    • 对于偶数长度的回文串,从i和i+1向两边扩展
  4. 对于每个找到的回文串s[j…i],更新dp[i] = min(dp[i], dp[j-1] + 1)
  5. 如果s[0…i]是回文串,则dp[i] = 0
  6. 返回dp[n-1]

时间复杂度:O(n^2),其中n是字符串的长度。
空间复杂度:O(n),只需要O(n)的空间存储dp数组。

图解思路

动态规划过程分析表

以示例1为例:s = “aab”

预处理回文串
isPalindrome[i][j]j=0j=1j=2
i=0truetruefalse
i=1-truefalse
i=2--true
计算最少分割次数
is[0…i]dp[i]初始值计算过程最终dp[i]说明
0“a”0s[0…0]是回文串,dp[0] = 00单个字符是回文串,不需要分割
1“aa”1s[0…1]是回文串,dp[1] = 00"aa"是回文串,不需要分割
2“aab”2s[0…2]不是回文串
s[1…2]不是回文串,dp[2] = min(dp[2], dp[0] + 1) = min(2, 0 + 1) = 1
s[2…2]是回文串,dp[2] = min(dp[2], dp[1] + 1) = min(1, 0 + 1) = 1
1"aab"需要分割一次

中心扩展法分析表

中心位置扩展类型找到的回文串更新dp[i]说明
0奇数长度“a”dp[0] = 0单个字符是回文串
0偶数长度“aa”dp[1] = 0"aa"是回文串
1奇数长度“a”dp[1] = min(dp[1], dp[0] + 1) = 0dp[1]已经是0,不更新
1偶数长度“ab”-"ab"不是回文串,不更新
2奇数长度“b”dp[2] = min(dp[2], dp[1] + 1) = min(2, 0 + 1) = 1更新dp[2] = 1

代码实现

C# 实现

public class Solution {public int MinCut(string s) {int n = s.Length;// 预处理回文串bool[,] isPalindrome = new bool[n, n];for (int i = 0; i < n; i++) {for (int j = 0; j <= i; j++) {if (s[j] == s[i] && (i - j <= 1 || isPalindrome[j + 1, i - 1])) {isPalindrome[j, i] = true;}}}// 计算最少分割次数int[] dp = new int[n];for (int i = 0; i < n; i++) {dp[i] = i; // 最坏情况下,需要i次分割if (isPalindrome[0, i]) {dp[i] = 0; // 如果s[0...i]是回文串,不需要分割continue;}for (int j = 0; j < i; j++) {if (isPalindrome[j + 1, i]) {dp[i] = Math.Min(dp[i], dp[j] + 1);}}}return dp[n - 1];}
}

Python 实现

class Solution:def minCut(self, s: str) -> int:n = len(s)# 预处理回文串is_palindrome = [[False] * n for _ in range(n)]for i in range(n):for j in range(i + 1):if s[j] == s[i] and (i - j <= 1 or is_palindrome[j + 1][i - 1]):is_palindrome[j][i] = True# 计算最少分割次数dp = list(range(n))  # 初始化dp[i] = ifor i in range(n):if is_palindrome[0][i]:dp[i] = 0  # 如果s[0...i]是回文串,不需要分割continuefor j in range(i):if is_palindrome[j + 1][i]:dp[i] = min(dp[i], dp[j] + 1)return dp[n - 1]

C++ 实现

class Solution {
public:int minCut(string s) {int n = s.length();// 预处理回文串vector<vector<bool>> isPalindrome(n, vector<bool>(n, false));for (int i = 0; i < n; i++) {for (int j = 0; j <= i; j++) {if (s[j] == s[i] && (i - j <= 1 || isPalindrome[j + 1][i - 1])) {isPalindrome[j][i] = true;}}}// 计算最少分割次数vector<int> dp(n);for (int i = 0; i < n; i++) {dp[i] = i; // 最坏情况下,需要i次分割if (isPalindrome[0][i]) {dp[i] = 0; // 如果s[0...i]是回文串,不需要分割continue;}for (int j = 0; j < i; j++) {if (isPalindrome[j + 1][i]) {dp[i] = min(dp[i], dp[j] + 1);}}}return dp[n - 1];}
};

执行结果

C# 实现

  • 执行用时:92 ms
  • 内存消耗:39.8 MB

Python 实现

  • 执行用时:1024 ms
  • 内存消耗:31.2 MB

C++ 实现

  • 执行用时:56 ms
  • 内存消耗:8.7 MB

性能对比

语言执行用时内存消耗特点
C#92 ms39.8 MB执行速度适中,内存消耗较高
Python1024 ms31.2 MB执行速度较慢,内存消耗适中
C++56 ms8.7 MB执行速度最快,内存消耗最低

代码亮点

  1. 🎯 使用动态规划预处理回文串,避免重复计算
  2. 💡 巧妙利用dp数组存储最少分割次数,状态转移清晰
  3. 🔍 优化判断条件,当s[0…i]是回文串时直接设置dp[i] = 0
  4. 🎨 代码结构清晰,逻辑简单易懂

常见错误分析

  1. 🚫 预处理回文串的状态转移方程错误,导致判断回文串不正确
  2. 🚫 初始化dp数组不正确,影响最终结果
  3. 🚫 没有考虑s[0…i]是回文串的特殊情况,导致计算错误
  4. 🚫 遍历顺序错误,导致状态转移不正确

解法对比

解法时间复杂度空间复杂度优点缺点
动态规划(预处理回文串)O(n^2)O(n^2)实现简单,思路清晰空间复杂度较高
优化的动态规划(中心扩展法)O(n^2)O(n)空间复杂度较低实现稍复杂
回溯(暴力枚举)O(2^n)O(n)思路直观时间复杂度高,会超时

相关题目

  • LeetCode 131. 分割回文串 - 中等
  • LeetCode 5. 最长回文子串 - 中等
  • LeetCode 647. 回文子串 - 中等
  • LeetCode 1745. 回文串分割 IV - 困难
  • LeetCode 1278. 分割回文串 III - 困难

相关文章:

LeetCode第132题_分割回文串II

LeetCode 第132题&#xff1a;分割回文串 II 题目描述 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是回文。 返回符合要求的 最少分割次数 。 难度 困难 题目链接 点击在LeetCode中查看题目 示例 示例 1&#xff1a; 输入&#xf…...

LabVIEW 在故障诊断中的算法

在故障诊断领域&#xff0c;LabVIEW 凭借其强大的图形化编程能力、丰富多样的工具包以及卓越的功能性能&#xff0c;成为工程师们进行故障诊断系统开发的得力助手。通过运用各种算法&#xff0c;能够对采集到的信号进行全面、深入的分析处理&#xff0c;从而准确地诊断出系统中…...

SQL DB 数据类型

SQL DB 数据类型 引言 在数据库管理系统中,数据类型是定义和存储数据的方式。SQL(结构化查询语言)数据库中的数据类型决定了数据的存储格式、大小、取值范围以及如何处理数据。合理选择和使用数据类型对于确保数据库性能、数据完整性和应用程序的准确性至关重要。 SQL 数…...

Qt音频输出:QAudioOutput详解与示例

1. 简介 QAudioOutput是Qt多媒体框架中的一个关键类&#xff0c;它提供了将PCM&#xff08;脉冲编码调制&#xff09;原始音频数据发送到音频输出设备的接口。作为Qt多媒体组件的一部分&#xff0c;QAudioOutput允许开发者在应用程序中实现音频播放功能&#xff0c;支持多种音…...

springboot 启动方式 装配流程 自定义starter 文件加载顺序 常见设计模式

目录 springboot介绍 核心特性 快速搭建 Spring Boot 项目 方式一&#xff1a;使用 Spring Initializr 方式二&#xff1a;使用 IDE 插件 示例代码 1. 创建项目并添加依赖 2. 创建主应用类 3. 创建控制器类 4. 运行应用程序 配置文件 部署和监控 部署 监控 与其…...

Android学习之Material Components

以下是 Material Design 提供的核心控件列表&#xff08;基于最新 Material Components for Android 库&#xff09;&#xff0c;按功能分类整理&#xff1a; 1. 基础按钮类 控件名称类名说明MaterialButtoncom.google.android.material.button.MaterialButton遵循 Material 规…...

sentinel新手入门安装和限流,热点的使用

1 sentinel入门 1.1下载sentinel控制台 &#x1f517;sentinel管理后台官方下载地址 下载完毕以后就会得到一个jar包 1.2启动sentinel 将jar包放到任意非中文目录&#xff0c;执行命令&#xff1a; java -jar 名字.jar如果要修改Sentinel的默认端口、账户、密码&#xff…...

Ubuntu 22 Linux上部署DeepSeek R1保姆式操作详解(Xinference方式)

一、安装步骤 1.基础环境安装 安装显卡驱动、cuda&#xff0c;根据自己硬件情况查找相应编号&#xff0c;本篇不介绍这部分内容&#xff0c;只给出参考指令&#xff0c;详情请读者自行查阅互联网其它参考资料。 sudo apt install nvidia-utils-565-server sudo apt install…...

ANTLR 实战_从零开始构建自定义语言解析器

1. 引言 1.1 什么是 ANTLR ANTLR(Another Tool for Language Recognition)是一个强大的解析器生成器,用于构建语言解析器、编译器和解释器。 1.2 ANTLR 的历史与发展 ANTLR 由 Terence Parr 创建,最初发布于 1995 年。经过多次版本更新,ANTLR 已成为构建解析器的首选工…...

CTF类题目复现总结-hashcat 1

一、题目地址 https://buuoj.cn/challenges#hashcat二、复现步骤 1、下载附件&#xff0c;解压得到What kind of document is this_文件&#xff1b; 2、用010 Editor打开What kind of document is this_文件&#xff0c;发现是office文件&#xff1b; 3、将后缀名改为ppt时…...

4月5日作业

需求&#xff1a; 1.按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2.要求SW 1为VLAN 2/3的主根及主网关 SW2为VLAN 20/30的主根及主网关&#xff0c;SW1和 SW2互为备份 3.可以使用super vlan 4.上层通过静态路由协议完成数据通信过程 5.AR1为企业出口路由器…...

Bert论文解析

文章目录 BERT&#xff1a;用于语言理解的深度双向转换器的预训练一、摘要三、BERT介绍BERT及其详细实现答疑&#xff1a;为什么没有标注的数据可以用来预训练模型&#xff1f;1. 掩码语言模型&#xff08;Masked Language Model, MLM&#xff09;2. 下一句预测&#xff08;Nex…...

无招回归阿里

这两天&#xff0c;无招回归阿里的新闻被刷屏了。无招创业成立的两氢一氧公司无招的股份也被阿里收购&#xff0c;无招以这种姿态回归阿里&#xff0c;并且出任钉钉的 CEO。有人说&#xff0c;这是对 5 年前“云钉一体”战略的纠偏。现在确实从云优先到 AI 优先&#xff0c;但云…...

初探:简道云平台架构及原理

一、系统架构概述 简道云作为一款低代码开发平台&#xff0c;其架构设计以模块化和云端协同为核心&#xff0c;主要分为以下层次&#xff1a; 1. 前端层 可视化界面&#xff1a;基于Web的拖拽式表单设计器&#xff0c;支持动态渲染&#xff08;React/Vue框架&#xff09;。多…...

LeetCode 热题 100 堆

215. 数组中的第K个最大元素 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 **k** 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 …...

面试常被问道OSPF的问题

面试中经常会涉及到OSPF相关的问题&#xff0c;作为网络工程师&#xff0c;我们对OSPF的了解可不能仅停留在“我知道它是路由协议”这么表面。 想面试官满意&#xff0c;拿到Offer&#xff0c;必须能回答得出细节&#xff0c;深度挖掘它的工作原理、配置技巧、以及应用场景。 …...

Redis(笔记)

简介&#xff1a; 常用数据类型: 常用操作命令&#xff1a; Redis的Java客户端&#xff1a; 操作字符串类型的数据&#xff1a; 操作Hash类型的数据&#xff1a; 操作列表类型的数据&#xff1a; 操作集合类型的数据&#xff1a; 操作有序集合类型数据&#xff1a; 通用命令…...

bootloader+APP中,有些APP引脚无法正常使用?

问&#xff1a;bootloaderAPP程序中&#xff0c;为什么有些APP引脚无法正常使用&#xff1f;无法设置高低电平 主控芯片GD32F415&#xff0c;参考案例bootloader中的引脚使用&#xff1a; 参考案例APP程序的引脚使用&#xff1a; 以及个人使用的无线模组&#xff0c;高电平使能…...

高并发内存池:原理、设计与多线程性能优化实践

高并发内存池是一种专门为多线程环境设计的内存管理机制&#xff0c;其核心目标是通过优化内存分配和释放过程&#xff0c;解决传统内存分配器&#xff08;如malloc/free&#xff09;在高并发场景下的性能瓶颈&#xff0c;显著提升多线程程序的内存访问效率。 目录 一、核心设计…...

基于内容的课程推荐网站的设计与实现00(SSM+htmlL)

基于内容的课程推荐网站的设计与实现(SSMhtml) 该系统是一个基于内容的课程推荐网站&#xff0c;旨在为用户提供个性化的课程推荐。系统包含多个模块&#xff0c;如教学视频、教学案例、课程信息、系统公告、个人中心和后台管理。用户可以通过首页访问不同的课程分类&#xff…...

生活电子常识--删除谷歌浏览器搜索记录

前言 谷歌浏览器会记录浏览器历史搜索,如果不希望看到越来越多的搜索记录,可以如下设置 解决 设置-隐私-自动填充表单 这个和浏览器记录的密码没有关系,可以放心删除...

学习threejs,使用Texture纹理贴图,测试repeat重复纹理贴图

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️Texture 纹理贴图1.1.1 ☘️…...

Git常用问题收集

gitignore 忽略文件夹 不生效 有时候我们接手别人的项目时&#xff0c;发现有的忽略不对想要修改&#xff0c;但发现修改忽略.gitignore后无效。原因是如果某些文件已经被纳入版本管理在.gitignore中忽略路径是不起作用的&#xff0c;这时候需要先清除本地缓存&#xff0c;然后…...

蓝桥杯基础算法-字符串与集合

对集合的考察集中在集合的特性和功能。 set-唯一性 list-有序性 集合元素的个数 思路分析&#xff1a;set的唯一性&#xff0c;取出重复的子串 eg&#xff1a; 下标0截取的范围&#xff1a;【0&#xff0c;最大下标】 下标1截取的范围&#xff1a;【1&#xff0c;最大下标…...

animals_classification动物分类

数据获取 深度学习训练中第一个是获取数据集&#xff0c;数据集的质量很重要&#xff0c;我们这里做的是动物分类&#xff0c;大致会选择几个动物&#xff0c;来做一个简单的多分类问题&#xff0c;数据获取的方法&#xff0c;鼠鼠我这里选择使用爬虫的方式来对数据进行爬取&a…...

对解释器模式的理解

对解释器模式的理解 一、场景1、题目【[来源](https://kamacoder.com/problempage.php?pid1096)】1.1 题目描述1.2 输入描述1.3 输出描述1.4 输入示例1.5 输出示例 二、不采用解释器模式1、代码2、“缺点” 三、采用解释器模式1、代码2、“优点” 四、思考1、解释器模式的意义…...

解决Oracle PL/SQL中“表或视图不存在“错误的完整指南

解决Oracle PL/SQL中"表或视图不存在"错误的完整指南 前言问题概述根本原因分析一、 编译时与运行时验证差异二、权限问题三、 Schema命名问题 实际案例演示案例1&#xff1a;动态分表查询案例2&#xff1a;权限不足的场景 实用排查步骤排查流程图最佳实践建议解决方…...

【Kubernetes】StorageClass 的作用是什么?如何实现动态存储供应?

StorageClass 使得用户能够根据不同的存储需求动态地申请和管理存储资源。 StorageClass 定义了如何创建存储资源&#xff0c;并指定了存储供应的配置&#xff0c;例如存储类型、质量、访问模式等。为动态存储供应提供了基础&#xff0c;使得 Kubernetes 可以在用户创建 PVC 时…...

linux如何查看当前系统的资源占用情况

在 Linux 系统中&#xff0c;有多个命令可以查看当前系统的资源占用情况。以下是一些常用的命令及其说明&#xff1a; 1. 查看内存使用情况&#xff1a;free free -h-h 参数表示以人类可读的格式显示&#xff08;如 MB, GB&#xff09;。输出示例&#xff1a; to…...

Arduino示例代码讲解:Row-Column Scanning an 8x8 LED matrix with X-Y input LED矩阵

Arduino示例代码讲解:Row-Column Scanning an 8x8 LED matrix with X-Y input LED矩阵 Row-Column Scanning an 8x8 LED matrix with X-Y input LED矩阵功能概述硬件部分:软件部分:代码逐行解释定义常量定义变量`setup()` 函数`loop()` 函数`readSensors()` 函数`refreshScr…...