LeetCode 132题详解:使用动态规划与中心扩展法解决分割回文串 II 的最少分割次数问题

简介: LeetCode 132题详解:使用动态规划与中心扩展法解决分割回文串 II 的最少分割次数问题

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣!

期待与您一起探索技术、持续学习、一步步打怪升级 欢迎订阅本专栏❤️❤️

在本篇文章中,我们将详细解读力扣第 132 题“分割回文串 II”。通过学习本篇文章,读者将掌握如何使用动态规划和中心扩展法来解决最小分割次数问题。

引言

分割回文串是字符串处理中的一个经典问题。它不仅在算法竞赛中经常出现,而且在文本处理、数据分析等领域也有广泛应用。本题要求我们将字符串分割成若干回文子串,并找到使得分割次数最少的方法。

问题描述

力扣第 132 题“分割回文串 II”描述如下:

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串。返回符合要求的 最少分割次数 。

示例 1:

输入: s = "aab"
输出: 1
解释: 只需一次分割就可将 s 分割成 ["aa","b"] 。

示例 2:

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

示例 3:

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

解题思路

初步分析

我们需要将字符串 s 分割成一些子串,使每个子串都是回文串,并找到最少的分割次数。

动态规划法
  1. 步骤
  • 预先计算并存储所有子串是否为回文子串。
  • 使用动态规划表 dp,其中 dp[i] 表示字符串 s[0:i] 的最少分割次数。
  • s[0:j+1] 是回文子串,则 dp[j+1] = min(dp[j+1], dp[i] + 1)
  1. 代码实现
def minCut(s):
    n = len(s)
    if n <= 1:
        return 0
    # 初始化回文判断表
    palindrome = [[False] * n for _ in range(n)]
    for right in range(n):
        for left in range(right + 1):
            if s[left] == s[right] and (right - left <= 2 or palindrome[left + 1][right - 1]):
                palindrome[left][right] = True
    # 初始化dp表
    dp = [float('inf')] * n
    for i in range(n):
        if palindrome[0][i]:
            dp[i] = 0
        else:
            for j in range(i):
                if palindrome[j + 1][i]:
                    dp[i] = min(dp[i], dp[j] + 1)
    return dp[n - 1]
# 测试案例
print(minCut("aab"))  # 输出: 1
print(minCut("a"))    # 输出: 0
print(minCut("ab"))   # 输出: 1
复杂度分析
  • 时间复杂度:O(N^2),其中 N 是字符串的长度。计算回文判断表和动态规划表都需要 O(N^2) 的时间。
  • 空间复杂度:O(N^2),用于存储回文判断表和动态规划表。
中心扩展法
  1. 步骤
  • 使用中心扩展法来判断所有可能的回文子串。
  • 使用动态规划来计算最少分割次数。
  1. 代码实现
def minCut(s):
    n = len(s)
    if n <= 1:
        return 0
    # 初始化dp表
    dp = list(range(n))
    
    # 中心扩展法判断回文子串
    for center in range(n):
        # 奇数长度回文
        l, r = center, center
        while l >= 0 and r < n and s[l] == s[r]:
            if l == 0:
                dp[r] = 0
            else:
                dp[r] = min(dp[r], dp[l - 1] + 1)
            l -= 1
            r += 1
        
        # 偶数长度回文
        l, r = center, center + 1
        while l >= 0 and r < n and s[l] == s[r]:
            if l == 0:
                dp[r] = 0
            else:
                dp[r] = min(dp[r], dp[l - 1] + 1)
            l -= 1
            r += 1
    return dp[-1]
# 测试案例
print(minCut("aab"))  # 输出: 1
print(minCut("a"))    # 输出: 0
print(minCut("ab"))   # 输出: 1
复杂度分析
  • 时间复杂度:O(N^2),其中 N 是字符串的长度。中心扩展法遍历所有可能的回文子串需要 O(N^2) 的时间。
  • 空间复杂度:O(N),用于存储动态规划表。

总结

本文详细解读了力扣第 132 题“分割回文串 II”,通过动态规划法和中心扩展法两种不同的解法,帮助读者深入理解最少分割次数问题的解决思路。希望读者通过本文的学习,能够在力扣刷题的过程中更加得心应手。

参考资料

  • 《算法导论》—— Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein
  • 力扣官方题解

🌹🌹如果觉得这篇文对你有帮助的话,记得一键三连关注、赞👍🏻、收藏是对作者最大的鼓励,非常感谢 ❥(^_-)

❤️❤️作者知识有限,如有错误,请各位大佬评论区批评指正,不胜感激❥(^_-)

欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
4月前
|
Python
【Leetcode刷题Python】131. 分割回文串
LeetCode题目131的Python编程解决方案,题目要求将给定字符串分割成所有可能的子串,且每个子串都是回文串,并返回所有可能的分割方案。
31 2
|
4月前
|
Python
【Leetcode刷题Python】416. 分割等和子集
LeetCode 416题 "分割等和子集" 的Python解决方案,使用动态规划算法判断是否可以将数组分割成两个元素和相等的子集。
40 1
|
6月前
|
缓存
力扣每日一题 6/14 动态规划+数组
力扣每日一题 6/14 动态规划+数组
41 1
|
6月前
|
存储 算法 数据可视化
深入解析力扣161题:相隔为 1 的编辑距离(逐字符比较与动态规划详解)
深入解析力扣161题:相隔为 1 的编辑距离(逐字符比较与动态规划详解)
|
6月前
|
算法 索引
力扣每日一题 6/28 动态规划/数组
力扣每日一题 6/28 动态规划/数组
55 0
|
6月前
|
存储
力扣每日一题 6/19 排序+动态规划
力扣每日一题 6/19 排序+动态规划
34 0
|
6月前
|
算法
力扣每日一题 6/16 字符串 + 随机一题 动态规划/数学
力扣每日一题 6/16 字符串 + 随机一题 动态规划/数学
48 0
|
6月前
力扣经典150题第二十五题:验证回文串
力扣经典150题第二十五题:验证回文串
39 0
|
6月前
|
机器人
【LeetCode】--- 动态规划 集训(二)
【LeetCode】--- 动态规划 集训(二)
45 0
|
6月前
【LeetCode】--- 动态规划 集训(一)
【LeetCode】--- 动态规划 集训(一)
37 0