【leetcode】5. Longest Palindromic Substring

【leetcode】5. Longest Palindromic Substring_第1张图片
给定字符串,求其最长的回文子字符串

方法1 暴力

暴力破解,遍历所有子字符串,判断是否为回文字符串,返回最长的那个
时间复杂度 o ( n 3 ) o(n^{3}) o(n3)
肯定TLE

class Solution:
    def longestPalindrome(self,s):
        maxlength = 0
        res = ""
        for i in range(len(s)):
            for j in range(i+1, len(s)+1):
                if self.isPalindrome(s[i:j]):
                    if j-i+1 > maxlength:
                        maxlength = j-i+1
                        res = s[i:j]
        return res


    def isPalindrome(self,s):
        if s[:(len(s)-1)//2+1] == s[len(s)//2:][::-1]:
            return True
        else:
            return False

方法2 DP法

使用动态规划法,要求最大的回文子字符串,可以将其分解为子问题,考虑递推方程,用dp[i][j]表示s[i:j+1]是否为回文字符串(是为1不是为0),那么递推方程可以写成如下形式

dp[i][j] =1    if s[i] = s[j] and dp[i+1][j-1] =1
否则
dp[i][j] = 0

由递推方程我们可以知道j要从小到大遍历,i要从大到小。并且i<=j
这里要稍微注意一下的是,如果 i和j相邻,只需要判断s[i] 和s[j]是否相等即可,因为此时i+1>j-1
这种方法的时间复杂度为 o ( n 2 ) o(n^{2}) o(n2)
AC代码

class Solution:
    """
    we use dp[i][j] to denote whether s[i:j+1] is palindrome or not
    we can easily get the comprehension dp[i][j] = True if  dp[i+1][j-1] is true and s[i] == s[j], it's not difficult
    from the comprehension we can find that, i depend on i+1, j depend on j -1, that tell us how to definite the loop.
    So the i should from lager to smaller and j should from smaller to larger.
    And the other important thing is that , i and j should from be adjacent at init state because the large palindrome depend on short palindrome

    """
    def longestPalindrome1(self, s):
        if len(s) == 0:
            return s
        left, right = 0,0
        dp = [[True if i == j else False for i in range(len(s))] for j in range(len(s))]
        for j in range(len(dp)):
            for i in range(j):
                if j - i == 1:
                    dp[i][j] = True if s[i] == s[j] else False
                else:
                    dp[i][j] =  dp[i+1][j-1] and s[i] == s[j]
                if dp[i][j] and j - i > right - left:
                    left, right = i, j
        return s[left:right+1]


class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        dp =[[0]*len(s) for i in range(len(s))]
        left,right,maxer = 0,0,0
        for j in range(len(s)):
            for i in range(j,-1,-1):
                if i == j:
                    dp[i][j] = 1
                elif j - i == 1:
                    dp[i][j] = 1 if s[i] == s[j] else 0
                else:
                    dp[i][j] = 1 if dp[i+1][j-1] == 1 and s[i] == s[j] else 0
                if dp[i][j] == 1 and j - i + 1 > maxer:
                    maxer = j - i +1
                    left,right = i,j
        return s[left:right+1]
           

simply

class Solution:
    def longestPalindrome(self, s):
        dp = [[0]*len(s) for i in range(len(s))]
        
        left,right = 0,0
        for i in range(len(dp)-1, -1,-1):
            for j in range(i,len(dp)):
                if i == j :
                    dp[i][j] = 1
                else:
                    dp[i][j] =1 if (i+1 == j or dp[i+1][j-1] ==1) and s[i] == s[j] else 0
                if dp[i][j] == 1:
                    if j - i > right - left:
                        left,right = i,j           
        return s[left:right+1]

beat 22%

方法3 中心扩散法

因为回文字符串分为中心对称和周对称两种,所以我们可以从左往右依次遍历字符串s,并考虑周对称和中心对称两种情况,分别以s[i]为中心,和以s[i]s[i+1]为轴往外扩展,找到最大的回文字符串
这样做的时间复杂度小于最坏情况下是 o ( n 2 ) o(n^{2}) o(n2),最好情况下可以接近 o ( n ) o(n) o(n)
AC代码

class Solution1(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        self.res,self.left,self.right =1,0,0
        for i in range(len(s)):
            self.pivot(i,i,s)
            self.pivot(i,i+1,s)
        return s[self.left:self.right+1]

    def pivot(self, i, j, s):
        if j >= len(s):
            return
        if s[i] != s[j] :
            return 0
        while(i >=0 and j < len(s)):
            if s[i] == s[j]:
                i -=1
                j +=1
            else:
                break
        if j - i - 1 > self.res:
            self.res = j - i - 1
            self.left,self.right = i+1,j-1

beat61%

你可能感兴趣的:(LeetCode)