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)
  2. 代码实现

    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. 步骤

    • 使用中心扩展法来判断所有可能的回文子串。
    • 使用动态规划来计算最少分割次数。
  2. 代码实现

    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
  • 力扣官方题解

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

❤️❤️作者知识有限,如有错误,请各位大佬评论区批评指正,不胜感激❥(^_-)
在这里插入图片描述

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据分析螺丝钉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值