代码改变世界

[LeetCode] 132. Palindrome Partitioning II_ Hard tag: Dynamic Programming

2019-04-25 11:14  Johnson_强生仔仔  阅读(288)  评论(0编辑  收藏  举报

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.

这个题目利用了两个dynamic programming的方式,先预处理s,得到所有substring的Palindrome表,T: O(n^2), S: O(n^2). 因为判断一个string是否为palindrome可以根据把首尾字母去掉之后的substring是否为palindrome,如果是,在判断首尾两个字母是否相等。如果不用dynamic programming可能会到T: O(n^3) 这个时间复杂度。

所以先从length小的来遍历一遍之后再依次遍历更长的substring,所以两个for loop要先loop length,然后再loop start position。

 

然后再通过mem[i] 去记录前i个字符的最小cut 的数量,为了方便for loop,因为要判断后面的substring是否为palindrome,如果是的话就+1, 这个时候会碰到如果从第一个字母到substring的最后一个字母是palindrome,结果应该是0, 但是前面加1了,所以需要用长度为n + 1 的mem去记录,初始化mem[0] = -1. 这里需要注意下标,因为在Palin的表格里面,下标就是s的下标,而mem中的下标是前n个字符。

Code:

class Solution:
    def minCut(self, s):
        if not s or len(s) == 1:
            return 0
        n = len(s)
        # pre deal with the Palindrome table
        palin = [[False]*n for _ in range(n)]
        for i in range(n):
            palin[i][i] = True
        for i in range(n - 1):
            palin[i][i + 1] = s[i] == s[i + 1]
        for l in range(2, n): # 下标是s的下标,所以是n
            for start in range(0, n - l): # s + l < n
                palin[start][start + l] = palin[start + 1][start + l - 1] and s[start] == s[start + l]
        # deal with the mem array
        mem = list(range(-1, n)) # if in python 3, range is an iterator
        for i in range(2, n + 1): # need to go to mem[n] which presents the first n characters
            for j in range(0, i):
                if palin[j][i - 1]: # i will be n, but palin is n * n
                    mem[i] = min(mem[i], mem[j] + 1)
        return mem[n]