LeetCode 热题 100 | 131. 分割回文串
大家好,今天我们来解决一道经典的回溯算法问题——分割回文串。这道题在 LeetCode 上被标记为中等难度,要求将一个字符串 s
分割成若干个子串,使得每个子串都是回文串,并返回所有可能的分割方案。
问题描述
给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是回文串。返回 s
所有可能的分割方案。
示例 1:
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a"
输出:[["a"]]
提示:
1 <= s.length <= 16
s
仅由小写英文字母组成
解题思路
核心思想
-
回溯法:
- 使用回溯法(Backtracking)来解决这个问题。
- 从字符串的起始位置开始,尝试所有可能的分割点,检查每个子串是否为回文串。
- 如果当前子串是回文串,则将其加入当前路径,并继续处理剩余部分。
- 如果到达字符串的末尾,则将当前路径加入结果列表。
-
辅助函数:
- 使用一个辅助函数
is_palindrome
来判断一个子串是否为回文串。
- 使用一个辅助函数
-
回溯过程:
- 使用一个递归函数
backtrack
,记录当前路径和处理到的位置。 - 在每次递归调用中,尝试所有可能的分割点,如果当前子串是回文串,则继续递归处理剩余部分。
- 使用一个递归函数
Python代码实现
class Solution:def partition(self, s: str) -> List[List[str]]:def is_palindrome(sub):return sub == sub[::-1]def backtrack(start, path):if start == len(s):result.append(path[:])returnfor end in range(start + 1, len(s) + 1):if is_palindrome(s[start:end]):path.append(s[start:end])backtrack(end, path)path.pop()result = []backtrack(0, [])return result
代码解析
-
辅助函数:
is_palindrome(sub)
:判断子串sub
是否为回文串。- 使用字符串反转的方法
sub == sub[::-1]
来判断。
-
回溯函数:
backtrack(start, path)
:从位置start
开始,尝试所有可能的分割点。- 如果到达字符串的末尾(
start == len(s)
),将当前路径path
加入结果列表result
。 - 对于每个可能的分割点
end
,检查子串s[start:end]
是否为回文串。 - 如果是回文串,则将其加入当前路径
path
,并递归处理剩余部分。 - 递归返回后,从路径中移除最后一个子串(回溯)。
-
主函数:
- 初始化结果列表
result
。 - 调用
backtrack(0, [])
,从字符串的起始位置开始处理。
- 初始化结果列表
复杂度分析
- 时间复杂度:O(2^n * n),其中
n
是字符串s
的长度。最坏情况下,每个位置都可能是一个分割点,需要尝试所有可能的分割方案。 - 空间复杂度:O(n),递归调用栈的深度最多为字符串的长度。
示例运行
示例 1
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例 2
输入:s = "a"
输出:[["a"]]
总结
通过回溯法,我们可以高效地解决分割回文串问题。回溯法的核心在于尝试所有可能的分割点,并通过辅助函数判断子串是否为回文串。希望这篇题解对大家有所帮助,如果有任何问题,欢迎在评论区留言讨论!
关注我,获取更多算法题解和编程技巧!