算法培训

第一节

最长回文子串

给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串。

样例

给出字符串 "abcdzdcab",它的最长回文子串为 "cdzdc"

挑战

O(n2) 时间复杂度的算法是可以接受的,如果你能用 O(n) 的算法那自然更好。

 

我的n^3代码:

class Solution:
    """
    @param s: input string
    @return: the longest palindromic substring
    """
    def longestPalindrome(self, s):
        # write your code here
        start, end = 0, 0
        for i in range(0, len(s)):
            for j in range(i, len(s)):
                if (j-i)>(end-start) and self.isPalind(s, i, j):
                    start, end = i, j
        return s[start:end+1]
    
    def isPalind(self, s, i, j):
        while i<j:
            if s[i] != s[j]:
                return False
            i += 1
            j -= 1
        return True

 从中心点左右遍历的解法,注意回文是奇偶情况,这才是这个题目的关键点:

 

class Solution:
    """
    @param s: input string
    @return: the longest palindromic substring
    """
    def longestPalindrome(self, s):
        # write your code here
        start,end = 0,0
        n = len(s)

        def locatePalindrome(s, i, j):
            nonlocal start,end
            while i>=0 and j<n:
                if s[i] == s[j]:
                    if end-start < j-i+1:
                        start,end = i,j+1
                else:
                    break
                i -= 1
                j += 1
                
        for i in range(n):
            # center i
            locatePalindrome(s, i, i)
            # center i,i+1
            locatePalindrome(s, i, i+1)
        return s[start:end]                        

 

DP解法:细节有点多,不一定能够写对。。。尤其是那个for是从大到小递减。

class Solution:
    """
    @param s: input string
    @return: the longest palindromic substring
    """
    def longestPalindrome(self, s):
        # write your code here
        start = end = 0
        n = len(s)
        dp = [[False]*n for _ in range(n)]
        for i in range(n-1, -1, -1): # for i in range(0, n) WRONG!!!!
            for j in range(i, n):
                if i == j: 
                    dp[i][j] = True
                else:
                    dp[i][j] = (s[i] == s[j]) and (j==i+1 or dp[i+1][j-1])
                if dp[i][j] and (j-i+1) > (end-start):
                    start, end = i, j+1
        return s[start:end]

 

Why is it not working if outside loop use for (int i = 0; i < n; i++)?

因为推导公式里 i 依赖于 i+1,所以i+1要比 i 先算出来,所以要倒过来循环。

 

 

posted @ 2019-01-12 10:23  bonelee  阅读(1003)  评论(0编辑  收藏  举报