LeetCode-Python-132. 分割回文串 II

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

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

第一种麻瓜思路:

把所有的分割可能全部找出来,然后找长度最小的分割可能,这个最小长度 - 1就是答案。

缺点:稳定超时。

class Solution(object):
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        res = self.partition(s)
        min_l = 2 ** 32
        for item in res:
            min_l = min(min_l, len(item))
        return min_l - 1
    def partition(self, s):
        """
        :type s: str
        :rtype: List[List[str]]
        """
        res = []
        
        def dfs(start, tmp):
            if start >= len(s): #结束条件
                res.append(tmp[:])
                return

            for i in range(start, len(s)):
                if s[start:i + 1] == s[start:i + 1][::-1]: #找到一个回文子串
                    tmp.append(s[start:i + 1])
                    dfs(i + 1, tmp ) #进行下一层搜索
                    tmp.pop() #回溯

        dfs(0, [])
        return res

第二种思路:

动态规划。

状态转移方程:

dp[i] = min(dp[i], dp[j] + 1) if dp[j : i] == dp[j : i][::-1]
class Solution(object):
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        if s == s[::-1]:
            return 0
        
        for i in range(1, len(s) + 1):
            if s[:i] == s[:i][::-1] and s[i:] == s[i:][::-1]:
                return 1
        #以上是进行预处理,因为testcase大多数答案都是0/1,所以可以加快速度
        
        dp = [i - 1 for i in range(len(s) + 1)]
        for i in range(1, len(s) + 1):
            for j in range(i):
                if s[j:i] == s[j:i][::-1]:
                    dp[i] = min(dp[i], dp[j] + 1)
                    
        return dp[-1]

第三种思路:

动态规划 + 中心拓展法。

找以每个字符为中心的长度最长的回文子串。

class Solution(object):
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        if s == s[::-1]:
            return 0
        
        for i in range(1, len(s) + 1):
            if s[:i] == s[:i][::-1] and s[i:] == s[i:][::-1]:
                return 1
        
        dp = [len(s) for i in range(len(s))]
        for i in range(0, len(s)):
            self.centeralExtend(s, i, i, dp)
            self.centeralExtend(s, i, i+1, dp)
        # print dp
        return dp[-1]
    
    def centeralExtend(self, string, left, right, dp):
        while left >= 0 and right < len(string) and string[left] == string[right]:
            if left > 0:
                dp[right] = min(dp[right], dp[left - 1] + 1)
            else:
                dp[right] = 0
            left -= 1
            right += 1

 

你可能感兴趣的:(Leetcode,Python)