Leetcode(5)最长回文子串

Leetcode(4)寻找两个有序数组的中位数

[题目表述]:

给定一个字符串 s,找到 s 中 最长 的回文子串。你可以假设 s 的最大长度为 1000。‘

第一种方法:未完成;利用回文子串的特点

一开始我的思路如下:回文子串的特点是首尾字母相同,所以我对每一个字母都找到位于它后面的相同字母,利用切片判断这一段是否为回文子串(str[i:j]==str[i:j][::-1]).时间复杂度很高,主要是因为str.find操作非常耗时.

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        res=""
        res+=s[0]
        res_star=0
        res_end=0
        Maxsize=1
        for i in range(len(s)):
            nPos=i
            i_number=s[i:].count(s[i])
            if i_number==1:
                continue
            while i_number!=1:
                if s[i+1]==s[i]:
                    i_number=i_number-1
                    nPos=i+1
                    if Maxsize!=max(Maxsize,len(s[i:nPos+1])):
                        Maxsize=len(s[i:nPos+1])
                        res_star,res_end=i,nPos+1
                        res+=s[i:nPos+1]
                else:
                    nPos=s[nPos+1:].index(s[i])
                    i_number=i_number-1
                    if s[i:nPos+1]==s[i:nPos+1:-1]:
                        if Maxsize!=max(Maxsize,len(s[i:nPos+1])):
                            res_star,res_end=i,nPos+1
                            res+=s[i:nPos+1]
        return res[res_star:res_end+1]

学习

  • str.find /str.index
  • 切片 回文子串

第二种方法:动态规划

执行用时:3828 ms; 内存消耗:11.7MB 效果:有点差 O(n2)

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        max = 0
        palindromic = '' if len(s) == 0 else s[0]
        for i in range(len(s)):
            length = 1
            while i - length >=0 and i + length < len(s) and s[i-length] == s[i+length]:
                tmp = s[i-length:i+length+1]        ##奇回文
                if len(tmp) > max:
                    max = len(tmp)
                    palindromic = tmp
                length += 1
            length = 1
            while i - length + 1  >=0 and i + length < len(s) and s[i-length+1] == s[i+length]:
                tmp = s[i-length+1:i+length+1]        ##偶回文
                if len(tmp) > max:
                    max = len(tmp)
                    palindromic = tmp
                length += 1
        return palindromic

学习

  • 动态规划的思想是首先判断相邻的字符串是否是回文,然后继续判断连续的三个字符是否是回文,然后是四个,…,直到判断完整个字符串 ——对子串的判断;状态转换
  • 动态规划思想
  • 奇偶回文

第三种方法:Manacher马拉车法:添加辅助标志

执行用时:80 ms; 内存消耗:12MB 效果:非常好 O(n)

[理论文章!]

class Solution:
    #Manacher algorithm
    #http://en.wikipedia.org/wiki/Longest_palindromic_substring

    def longestPalindrome(self, s):
        # Transform S into T.
        # For example, S = "abba", T = "^#a#b#b#a#$".
        # ^ and $ signs are sentinels appended to each end to avoid bounds checking
        T = '#'.join('^{}$'.format(s))
        n = len(T)
        P = [0] * n
        C = R = 0
        for i in range (1, n-1):    ##首尾是终止符
            P[i] = (R > i) and min(R - i, P[2*C - i]) # equals to i' = C - (i-C)   #如果R>i且R-i大,则P[i]=P[j]
            # Attempt to expand palindrome centered at i                             两者相等,因为R范围内对称
            while T[i + 1 + P[i]] == T[i - 1 - P[i]]:
                P[i] += 1

            # If palindrome centered at i expand past R,
            # adjust center based on expanded palindrome.
            if i + P[i] > R:    #最终求出P[i]后设立新C,R C=center R=range 利用2*C-i拉着i走一样
                C, R = i, i + P[i]

        # Find the maximum element in P.
        maxLen, centerIndex = max((n, i) for i, n in enumerate(P))
        return s[(centerIndex  - maxLen)//2: (centerIndex  + maxLen)//2]    #因为len(P)=len(s)两倍多 

学习:

  • 两头需要边界符
  • 字符.join
  • 马拉车算法思想
  • list.enumerate()

第四种方法:新增字母判断是否仍是回文

执行用时:72 ms; 内存消耗:11.8MB 效果:非常好 O(n) 由于使用切片,所以比马拉车快

class Solution:
    # @return a string
    def longestPalindrome(self, s):
        if len(s)==0:
            return s
        maxLen=1
        start=0
        for i in xrange(len(s)):
            if i-maxLen >=1 and s[i-maxLen-1:i+1]==s[i-maxLen-1:i+1][::-1]:
                start=i-maxLen-1
                maxLen+=2
                continue

            if i-maxLen >=0 and s[i-maxLen:i+1]==s[i-maxLen:i+1][::-1]:
                start=i-maxLen
                maxLen+=1
        return s[start:start+maxLen]

学习

  • 思路是:遍历,第i个字母加上后面一个字母,看i-Max-1到i+1(就是从第i个往后面看)是不是回文,如果是,则回文串起点跟Max被记录下来;如果这样不是,那就看i-Max到i+1是不是回文,如果是也是一样的操作。
  • 因为前面字符串加上新的字符是回文的话,就只有两种可能性,
    ①:bb+b这种 ②:a bb+a这种,①记录下Max=2,
    ②则在a前面Max+1找,即是i-Max-1,然后记录下Max=3,
    做切片的时候就是start:start+Max,Max自动会-1的,保证半径符合。

原文地址:https://www.cnblogs.com/ymjun/p/11645119.html

时间: 2024-10-10 18:02:29

Leetcode(5)最长回文子串的相关文章

LeetCode -- 5 -- 最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案. 示例 2: 输入: "cbbd" 输出: "bb" std::string longestPalindrome(std::string s) { const int len = s.size(); if(1 >= len)

LeetCode 5. 最长回文子串 Longest Palindromic Substring

题目: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案. 示例 2: 输入: "cbbd" 输出: "bb"  解法一 遍历字符串,以每个字母为中心,向两边扩散查找,记录当前最长的回文子串的长度和起始位置.结尾位置.时间复杂度O(n^2) 注意: ①当剩下的字符串长度小于当前m

leetcode 5 最长回文子串问题

题目描述 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad"输出: "bab"注意: "aba" 也是一个有效答案.示例 2: 输入: "cbbd"输出: "bb" 方法一暴力求解: 定义一个n*n维的数组flage,flage[i][j] 表示以i开始,以j结束的回文串的长度,如果Si,,,,,,Sj是回文串,那么flage[i][

[LeetCode系列] 最长回文子串问题

给定字符串S, 找到其子串中最长的回文字符串. 反转法: 反转S为S', 找到其中的最长公共子串s, 并确认子串s在S中的下标iS与在S'中的下标iS'是否满足式: length(S) = iS + iS' + length(s). 如果满足则s为搜索结果, 如果不满足我们就继续搜索. DP解法: 定义 P[i][j] = true  <-> Si...Sj是回文串, 否则为false; 则有 P[i+1][j-1] = true && Si = Sj <-> P[

【Leetcode】最长回文子串

中心扩散法 我们观察到回文中心的两侧互为镜像.因此,回文可以从它的中心展开,并且只有 2n−1 个这样的中心. 你可能会问,为什么会是 2n−1 个,而不是 n 个中心?原因在于所含字母数为偶数的回文的中心可以处于两字母之间(例如“abba” 的中心在两个‘b’ 之间). 时间复杂度 O(n^2), 由于围绕中心来扩展回文会耗去 O(n) 的时间,所以总的复杂度为 O(n^2); 空间复杂度 O(1); 执行用时 : 128 ms, 在Longest Palindromic Substring的

【数据结构与算法】动态规划——最长回文子串

最长回文子串 LeetCode:最长回文子串 题目描述: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案. 思想: 动态规划,用boolean[][] dp记录每一对字符是否相等: 双循环遍历所有子串情况,每次遍历时,当前子串首尾相等且内层-1字符串dp值为true,则记录dp值为true:全部遍历完,取最长,即为最

LeetCode之“字符串”:最长回文子串

题目要求: 给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串.例如,给出字符串 "abcdzdcab",它的最长回文子串为 "cdzdc". 解答: 这个题目的一个简单的解法就是对字符串中的每一个字符,同时向其两边延展,以找到最长回文子串.这种方法是可以的,但要处理回文子串长度为奇数和偶数的两种情况是比较麻烦的.如下图的几个字符串: “a” "aa" "aaa" "

【LeetCode】5# 最长回文子串

题目描述 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案. 示例 2: 输入: "cbbd" 输出: "bb" 思路 本题运用了一些动态规划的思想,关于动态规划,可以看看我之前的一篇博客了解一下. LeetCode 探索初级算法 - 动态规划 1.首先要找到最简情况.这道题

[C++]LeetCode: 99 Longest Palindromic Substring (最长回文子串)

题目:Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 思路:题目要求的s的一个最长回文子串.暴力解决办法就是枚举所有的子串,再对每个子串进行回文判断.进行剪枝,我们考虑可以使用动态规划来避免重复的判

leetcode 5 :Longest Palindromic Substring 找出最长回文子串

题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 翻译: 找出字符串s中最长的回文子串,字符串s的最长是1000,假设存在唯一的最长回文子串 法一:直接暴力破解 O(N3)的时间复杂度,运行超