Leetcode 132:分割回文串 II(最详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/85482167

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。

返回符合要求的最少分割次数。

示例:

输入: "aab"
输出: 1
解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

解题思路

这个问题是之前问题的提高?Leetcode 131:分割回文串(最详细的解法!!!)

一个简单的动态规划问题。我们定义函数 f ( i ) f(i) 表示s[:i]的最小分割次数。我们我们只需要找到i之前的一个位置j,使得s[j:i]是一个回文串,那么就可以得到这样的递推公式

  • f ( i ) = m i n ( f ( j ) + 1 )    f o r   j   i n   r a n g e ( i ) f(i)=min(f(j)+1)\ \ for\ j\ in\ range(i)
class Solution:
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        if not s:
            return 0
        
        s_len = len(s)
        mem = [i for i in range(-1, s_len)]
        for i in range(1, s_len + 1):
            for j in range(i):
                if s[j:i] == s[j:i][::-1]:
                    mem[i] = min(mem[i], mem[j] + 1)
                    
        return mem[-1]

恩,虽然通过了,但是我们这个算法的时间复杂度依旧非常高。其实这个问题就是最长回文子串问题的变种。我们可以参考Leetcode 5:最长回文子串(最详细的解法!!!)最后的一种做法。我们首先建立r1r2,分别表示偶数回文串的半径长度和奇数回文串的半径长度。然后我们遍历s中的每个字符串,分别以每个字符串为圆心找到最长的回文串。假设圆心是i,我们可以得到下面两个式子:

  • f ( i + r 1 + 1 ) = m i n ( f ( i + r 1 + 1 ) , f ( i r 1 ) + 1 ) f(i+r_1+1) = min(f(i+r_1+1), f(i-r_1)+1)
  • f ( i + r 2 + 2 ) = m i n ( f ( i + r 2 + 2 ) , f ( i r 2 ) + 1 ) f(i+r_2+2) = min(f(i+r_2+2), f(i-r_2)+1)
class Solution:
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        if s == s[::-1]: 
            return 0   
        
        for i in range(1, len(s)):
            if s[:i] == s[:i][::-1] and s[i:] == s[i:][::-1]:
                return 1
        
        mem = list(range(-1,len(s)))
        for i in range(len(s)):
            r1, r2 = 0, 0
            
            while i-r1 >= 0 and i+r1 < len(s) and s[i-r1] == s[i+r1]:
                mem[i+r1+1] = min(mem[i+r1+1],mem[i-r1]+1)
                r1 += 1
                
            while i-r2 >= 0 and i+r2+1 < len(s) and s[i-r2] == s[i+r2+1]:
                mem[i+r2+2] = min(mem[i+r2+2],mem[i-r2]+1)
                r2 += 1
                
        return mem[-1] 

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/85482167