问题:
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
解题思路:
这是一道看似简单,但实操起来还是比较麻烦的一道题目。最近对哈希算法比较热衷,因此,看到题目的第一眼,也就想到了可以用哈希算法求解,因为这也是一道查找相关的题目。
我的解题方法如下:
1)首先理解回文的定义。即子串翻转前后一致,由此,假定翻转钱子串为temp,翻转后子串为temp2,则判断temp与temp2是否相等,即可判断temp是否满足回文。
2)接下来考虑子串的截取问题。个人认为,也就是这道题最关键的考点。如果是回文,则截取的子串开头和结尾必然相同,由此,字典也就排上了用场,键为字符串的字符,而值,即为字符对应的下标值,这里我们要保存字符在字符串所有的下标值,因此值以列表的形式存储(实现时注意字符还未添加进字典时,下标的实现方式)。
3)字典的遍历问题。设定好第二步后,也就是我们该怎么使用字典呢,这里考虑用三层循环去实现,第一层即为字典的键值得遍历,第二层和第三层结合起来,实现对子串的截取和判断子串是否为回文(看似三层循环,复杂度其实远远小于O(n3)的)。
4)另外一些变量的设置问题。肯定需要一个变量,来保存结果,这里用subset来记录;还需要一个变量来记录当前遍历过的回文的最大长度,这里用sublen记录。
5)其他特殊情况的考虑。一种是字符串为空或者只有一个字符;另一种是字符串没有相同的两个字符。
python程序具体实现如下:
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
# 情况一:如果字符串为空或者长度为1
if len(s)<2:
return s
sDict = {} # 字典存储,键为字符,值为字符的下标
for i in range(len(s)):
if s[i] in sDict.keys():
sDict[s[i]].append(i)
else:
sDict[s[i]]=[i]
subset = '' #记录最长回文
sublen = 0 #记录当前回文中的最大长度
# 情况二:一般情况下的字符串回文判断
for k in sDict.keys():
for i in sDict[k]:
for j in sDict[k]:
if j<=i:
continue
else:
temp = s[i:j+1] # 子串截取
temp2 = temp[::-1] # 子串翻转
if temp==temp2 and len(temp)>=sublen:
sublen = len(temp)
subset = temp
# 情况三:如果字符串中的每个字符均不相同,则情况二后的sublen长度仍为0
if sublen==0:
subset=s[-1]
return subset
题外话:
这次的实现自己还是比较满意的,提交次数如下图,两次失败的原因,一次就是特殊情况一的忽视,一次就是特殊情况二的忽视,总之,这次自己很快就发现了问题所在吧,小庆幸吧。目前自己的算法肯定不是最优,看官方说有O(n)级的算法——Manacher 算法,后续学习了在补充上吧。
今天跑完步看到的一句话,共勉: