1.前言
研究生最后一年,到了招工作的时刻,开始刷题。记录刷题过程。
2、leetcode 5. 最长回文子串
首先我选择的算法类题目,其次是从字符串相关的题目做起,因为字符串是最常见的笔试题目类型,相关的题目也是千变万化的,很多算法都是在字符串的基础上改进的。
题目:
给定一个字符串
s
,找到s
中最长的回文子串。你可以假设s
的最大长度为 1000。输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。
该题目有多种解决方法。暴力计算(得到所有的子字符串进行判断);动态规划;中心枚举;以及matcher。
至于暴力计算由于时间复杂度和空间复杂度都比较高,一般是无法通过测试的。
动态规划
对于动态规划的思路是:如果一个字符串是回文串,那么去掉第一个字符和最后一个字符也应该是回文串。因此,根据这个思想。我们先从最短的子串来判断。结合动态规划的思想,使用一个矩阵P[i,j]来表示子串s[i:j+1]是否为回文串。
p[i,i]=1
p[i,j]=1 if s[i]==s[j] and p[i+1,j-1]==1 else 0
那么利用代码实现:(python)
def t(s): length = len(s) if length <2: return s import numpy as np p = np.eye(length) start = 0 end = 0 for k in range(1,length): for i in range(length): if i+k <length: if k==1: if s[i]==s[i+k]: p[i,i+k] =1 if k+1 > end -start+1: start = i end = i+k else: if s[i] == s[i+k] and p[i+1,i+k-1] ==1: p[i,i+k] =1 if k+1 > end -start+1: start = i end = i+k return s[start:end+1]
中心枚举
中心枚举的思路是分别计算两种回文串:长度为奇数和长度为偶数的。
def t(s):
length = len(s)
start = 0
maxlen = 0
if length <2:
return s
for i in range(1,length): //计算偶数个
low = i-1
high = i
while high<length and low>=0 and s[low]==s[high]:
if maxlen < high - low:
start = low
maxlen = high-low
low = low -1
high = high +1
for i in range(1,length): //计算奇数个
low = i-1
high = i+1
while high<length and low>=0 and s[low]==s[high]:
if maxlen < high - low:
start = low
maxlen = high-low
low = low -1
high = high +1
return s[start:start+maxlen+1]
matcher
该方法的特点就是将字符串的个数变成为奇数个之后再次查找,将字符串的每个字符之间添加特殊字符#。
def t2(s):
if len(s)<2:
return s
s = "#"+"#".join(s)+"#" #将字符串每个字符之间添加字符#,得到新的字符串的长度一定是奇数
start = 0
maxlen = 0
for i in range(len(s)):
low = i-1
high = i+1
while low >=0 and high <len(s) and s[low]==s[high]:
if maxlen < high - low:
start = low
maxlen = high-low
low = low -1
high = high +1
# print("index:",start,maxlen,s[start:maxlen+1])
same = s[start:start+maxlen+1].replace("#","")
return same