diff --git a/docs/Leetcode_Solutions/Python/0132._Palindrome_Partitioning_II.md b/docs/Leetcode_Solutions/Python/0132._Palindrome_Partitioning_II.md new file mode 100644 index 0000000000000000000000000000000000000000..c65a8022e9ece821d8ea5cfbab58e8195533ac50 --- /dev/null +++ b/docs/Leetcode_Solutions/Python/0132._Palindrome_Partitioning_II.md @@ -0,0 +1,123 @@ +# 132. Palindrome Partitioning II + +**难度: Hard** + +## 刷题内容 + +> 原题连接 + +* https://leetcode.com/problems/palindrome-partitioning-ii/ + +> 内容描述 + +``` +Given a string s, partition s such that every substring of the partition is a palindrome. + +Return the minimum cuts needed for a palindrome partitioning of s. + +Example: + +Input: "aab" +Output: 1 +Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut. +``` + +## 解题方案 + +> 思路 1 +******- 时间复杂度: O(N^3)******- 空间复杂度: O(N^2)****** + +- 我们维护一个一维数组cut,cut[i]代表s[:i+1]最少需要多少次cut +- 然后我们发现对于j<=i, 如果s[j:i+1]是Palindrome。则cut[i] = min(cut[i], cut[j-1] + 1) if j > 0 else 0, +因为如果j为0的话说明s[:i+1]都是Palindrome了,完全不需要cut,所以当j==0的时候cut[i] = 0 +- 最后返回cut[-1]即可 + +```python +class Solution: + def minCut(self, s: str) -> int: + cut = list(range(len(s))) + for i in range(len(s)): + for j in range(i+1): + if s[j:i+1] == s[j:i+1][::-1]: + cut[i] = min(cut[i], cut[j-1] + 1) if j > 0 else 0 + return cut[-1] +``` + +> 思路 2 +******- 时间复杂度: O(N^2)******- 空间复杂度: O(N^2)****** + +我们发现每次都要算s[j:i+1]是否为Palindrome太浪费时间了, 用一个dp数组记录一下 + +- 我们维护一个二维数组dp,dp[i][j]代表s[i:j+1]是否为Palindrome +- 然后维护一个一维数组cut,cut[i]代表s[:i+1]最少需要多少次cut +- 然后我们发现对于j<=i, 如果s[j:i+1]是Palindrome。则cut[i] = min(cut[i], cut[j-1] + 1) if j > 0 else 0, +因为如果j为0的话说明s[:i+1]都是Palindrome了,完全不需要cut,所以当j==0的时候cut[i] = 0 +- 最后返回cut[-1]即可 + + +```python +class Solution: + def minCut(self, s: str) -> int: + dp = [[False] * len(s) for _ in range(len(s))] + cut = [0] * len(s) + for i in range(len(s)): + cut[i] = i + for j in range(i+1): + if s[i] == s[j] and (j+1 >= i-1 or dp[j+1][i-1]): + dp[j][i] = True + cut[i] = min(cut[i], cut[j-1] + 1) if j > 0 else 0 + return cut[-1] +``` + + +> 思路 3 +******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)****** + +我们在空间上也可以继续优化 + +- 我们维护一个一维数组cut,cut[i] 代表前i个字符最少需要几次cut +- 然后对于每一个字符s[i],我们分两种情况讨论 + - 将s[i]作为palindrome的中间字符(odd length),向两边各扩展j个字符,使得s[i-j:i+j+1]是palindrome,同时保证不越界, + 此时cut[i+j+1] = min(cut[i+j+1], cut[i-j] + 1) + - 将s[i]作为palindrome的中间靠前的那个字符(even length),向左边扩展j-1个字符,向右边扩展j个字符,使得s[i-j+1:i+j+1]是palindrome,同时保证不越界, + 此时cut[i+j+1] = min(cut[i+j+1], cut[i-j+1] + 1) +- 最后返回cut[-1] +```python +class Solution: + def minCut(self, s: str) -> int: + cut = list(range(-1, len(s))) # cut[i] 代表前i个字符最少需要几次cut + for i in range(len(s)): + j = 0 + while i - j >= 0 and i + j < len(s) and s[i-j] == s[i+j]: # odd length palindrome + cut[i+j+1] = min(cut[i+j+1], cut[i-j] + 1) + j += 1 + j = 1 + while i - j + 1 >= 0 and i + j < len(s) and s[i-j+1] == s[i+j]: # even length palindrome + cut[i+j+1] = min(cut[i+j+1], cut[i-j+1] + 1) + j += 1 + return cut[-1] +``` + + + + + + + + + + + + + + + + + + + + + + + +