LeetCode 131题详解:高效分割回文串的递归与动态规划方法

简介: LeetCode 131题详解:高效分割回文串的递归与动态规划方法

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

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

在本篇文章中,我们将详细解读力扣第 131 题“分割回文串”。该问题在字符串处理和动态规划中非常常见,通过学习本篇文章,读者将掌握高效解决此类问题的技巧。

问题描述

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

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

示例 1:

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

示例 2:

输入: "a"
输出: [["a"]]

解题思路

  1. 初步分析
  • 我们需要将字符串 s 分割成一些子串,使每个子串都是回文串。
  • 回文串是指正读和反读都相同的字符串。
  1. 递归+回溯法
  • 我们可以用递归+回溯的方法来解决这个问题。
  • 从字符串的第一个字符开始,逐个尝试分割,如果前面的部分是回文,则继续分割剩下的部分。
  • 通过回溯来记录每次分割的结果。
  1. 动态规划法
  • 我们还可以用动态规划来优化判断回文的过程。
  • 预先计算并存储所有子串是否为回文串,避免重复判断。

解法一:递归+回溯法

  1. 步骤
  • 从字符串的第一个字符开始,逐个尝试分割。
  • 每次分割后,判断前面的部分是否为回文。
  • 如果是回文,则递归处理剩下的部分。
  • 通过回溯来记录每次分割的结果。
  1. 伪代码
def backtrack(start, path):
    if start == len(s):
        result.append(path)
        return
    for end in range(start, len(s)):
        if is_palindrome(s, start, end):
            backtrack(end + 1, path + [s[start:end + 1]])

代码实现

解法一:递归+回溯法
def partition(s):
    def is_palindrome(sub_s):
        return sub_s == sub_s[::-1]
    def backtrack(start, path):
        if start == len(s):
            result.append(path[:])
            return
        for end in range(start, len(s)):
            if is_palindrome(s[start:end + 1]):
                backtrack(end + 1, path + [s[start:end + 1]])
    
    result = []
    backtrack(0, [])
    return result

复杂度分析

  • 时间复杂度:O(N * 2^N),其中 N 是字符串的长度。每个字符都有分割和不分割两种选择。
  • 空间复杂度:O(N),用于递归调用的栈空间。

代码优化

解法二:动态规划法
  1. 步骤
  • 预先计算并存储所有子串是否为回文串。
  • 使用动态规划表 dp,其中 dp[i][j] 表示字符串 s 的子串 s[i:j+1] 是否为回文。
  • 使用回溯法来找到所有分割方案。
  1. 伪代码
def partition(s):
    dp = [[False] * len(s) for _ in range(len(s))]
    for right in range(len(s)):
        for left in range(right + 1):
            if s[left] == s[right] and (right - left <= 2 or dp[left + 1][right - 1]):
                dp[left][right] = True
    def backtrack(start, path):
        if start == len(s):
            result.append(path[:])
            return
        for end in range(start, len(s)):
            if dp[start][end]:
                backtrack(end + 1, path + [s[start:end + 1]])

代码实现

解法二:动态规划法
def partition(s):
    n = len(s)
    dp = [[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 dp[left + 1][right - 1]):
                dp[left][right] = True
    def backtrack(start, path):
        if start == n:
            result.append(path[:])
            return
        for end in range(start, n):
            if dp[start][end]:
                backtrack(end + 1, path + [s[start:end + 1]])
    
    result = []
    backtrack(0, [])
    return result

复杂度分析

  • 时间复杂度:O(N^2) 计算动态规划表需要 O(N^2) 的时间,回溯的时间复杂度在最坏情况下仍为 O(N * 2^N)。
  • 空间复杂度:O(N^2) 用于存储动态规划表。

测试案例

def test_partition():
    assert partition("aab") == [["a","a","b"], ["aa","b"]]
    assert partition("a") == [["a"]]
    assert partition("racecar") == [["r","a","c","e","c","a","r"], ["r","aceca","r"], ["racecar"]]
    assert partition("aaa") == [["a","a","a"], ["a","aa"], ["aa","a"], ["aaa"]]
test_partition()

总结

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

参考资料

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

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

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

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

相关文章
|
3月前
|
存储
LeetCode------递归(爬楼梯)
这篇文章通过LeetCode上的"爬楼梯"问题介绍了递归的基本概念和实现方法,包括递归公式的推导、基本递归实现、使用备忘录优化以避免重复计算,以及自底向上的迭代方法来提高效率。
LeetCode------递归(爬楼梯)
|
3月前
|
Python
【Leetcode刷题Python】416. 分割等和子集
LeetCode 416题 "分割等和子集" 的Python解决方案,使用动态规划算法判断是否可以将数组分割成两个元素和相等的子集。
29 1
|
3月前
|
Python
【Leetcode刷题Python】131. 分割回文串
LeetCode题目131的Python编程解决方案,题目要求将给定字符串分割成所有可能的子串,且每个子串都是回文串,并返回所有可能的分割方案。
21 2
|
5月前
|
缓存
力扣每日一题 6/14 动态规划+数组
力扣每日一题 6/14 动态规划+数组
37 1
|
5月前
|
算法 Python
LeetCode 常用方法
LeetCode 常用方法
|
5月前
|
算法 索引
力扣每日一题 6/28 动态规划/数组
力扣每日一题 6/28 动态规划/数组
52 0
|
5月前
|
存储
力扣每日一题 6/19 排序+动态规划
力扣每日一题 6/19 排序+动态规划
30 0
|
5月前
|
算法
力扣每日一题 6/16 字符串 + 随机一题 动态规划/数学
力扣每日一题 6/16 字符串 + 随机一题 动态规划/数学
44 0
|
5月前
力扣经典150题第二十五题:验证回文串
力扣经典150题第二十五题:验证回文串
35 0
|
5月前
|
机器人
【LeetCode】--- 动态规划 集训(二)
【LeetCode】--- 动态规划 集训(二)
38 0