今天刷leetcode时遇到的最长回文子串问题:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 输入: "cbbd" 输出: "bb"
我用的是Manacher算法算法,时间复杂度O(n)),为什么代码在执行时反倒没有中心扩展算法(时间复杂度O(n^2))的快呢?
下面是我的代码:
class Solution: def longestPalindrome(self, s): """ :type s: str :rtype: str """ if len(s) == 1: return s # 预处理,添加字符'#'解决字符串长度分奇偶的问题 ss = '#' + '#'.join(s) + '#' # 初始化 pos = 0 # 对称轴 maxpos = 0 # 最大位置 maxright = 0 # 最大右边界 lenss = len(ss) # 字符串长度 p = [0] * lenss # 对称半径列表 # 主循环 for i in range(lenss): # 判断是否在右边界以内 if i < maxright: # 设置p[i]的值 p[i] = min(p[2*pos-i], maxright-i) else: p[i] = 1 # 当没有到字符串首或尾时扩展边界 while ((i - p[i]) > 0) and ((i + p[i]) < lenss) and (ss[i-p[i]] == ss[i+p[i]]): p[i] += 1 # 更新边界 if maxright < i + p[i] -1: maxright = i + p[i] -1 pos = i # 更新最大索引 if p[i] > p[maxpos]: maxpos = i return ss[maxpos-(p[maxpos]-1):maxpos+p[maxpos]].replace('#','')
东方不败
其实不管是否是中心测试法,还是其他的测试法,都肯定是第二层循环。而核心拼速度的就是减枝(虽然这不是深度搜索,但是也是适用的)。用已经获得的最大的值去测试一下,如果行,继续扩大长度来实验;如果不行,那就说明这个点测试不出来更大的,那就不用继续去实验了。这样就可以很明智地撸一遍,撸得很轻松。
这应该属于动态规划的思路。
jerkzhang
乍看一下,你这似乎有两层循环~ while也是循环吧,另外while这么来写,我感觉有点变扭,不过也许是我个人习惯吧(我会使用while true加break跳出来写,不过这是细节,很可能是我个人习惯,最终形成了我的阅读逻辑习惯,我感觉这样写逻辑上会更清楚;不过这个事情很细节,而且是一个有争议的细节。不用管)
不管哪种算法,如果是追求速度与效率;我感觉有相当多的情况下都是空间换速度。