题目描述
补充一点: 回文串就是正着读和反着读都一样的字符串。
解题思路
题目看着很简单不是吗? 实则不然,算法题越是题目描述的简单的,可能背后的逻辑就越复杂。
一个顺着题目描述的解法
一个比较容易想到的解法是:首先判断字符串的长度,如果长度为0或者1,那么就可以直接返回了,本身就是最长回文子串。
如果长度为2,那么就判断这个字符串所包含的两个字符是不是一样的字符,如果是,那么返回字符串本身,如果不是,那么返回字符串的第一个字符。
如果字符串长度大于2,那么需要遍历字符串,每次遍历时判断子字符串是不是回文子串,如果是的话,那就直接返回。
如果字符串以上条件都不满足,即它长度大于2,并且内部没有长度大于1的回文子串,那就返回字符串的第一个字符。
根据上面的思路可以完成代码。
class Solution:
def longestPalindrome(self, s: str) -> str:
res = ''
if len(s) <= 1:
return s
if len(s) == 2:
if s[0] == s[1]:
return s
else:
return s[0]
for i in range(len(s)):
rest = s[i+1:]
temp_s = s[i]
for j in rest:
temp_s += j
if temp_s == temp_s[::-1]:
res = temp_s if len(temp_s) >= len(res) else res
if res == '':
return s[0]
return res
尝试提交,通过,时间复杂度为O(n^3)
。
有优雅一些的解法吗?当然😎
很显然上面那种解法不断的判断字符串的长度,太不优雅了!
经过思考,题目要求的是最长回文子串,那么我们换个思路,从字符串本身去最长子串,每次判断最长字串是否为回文子串,如果是,那么它肯定就是最长回文子串,那么就返回,如果不是,那么就缩短最长子串的长度,继续判断。
这就类似于滑动窗口的思想,比如输入的字符串长度为10,那么就直接令窗口大小为10,判断窗口内的字符串是否为回文子串,如果是,那么就返回,如果不是,那么就缩短窗口大小,通过不断在父字符串上的滑动继续判断。
开始手搓!
class Solution:
def longestPalindrome(self, s: str) -> str:
res = s[0]
window = len(s)
while window >= 1:
for i in range(len(s)-window+1):
temp_s = s[i:i+window]
if temp_s == temp_s[::-1]:
res = temp_s if len(temp_s) > len(res) else res
return res
window -= 1
return res
通过不断的减小窗口大小,就能够第一时间找出最长回文子串。
尝试提交,通过,时间复杂度为O(n^3)
,好像跟上面的解法是一样的时间消耗,但是可以看到运行所花的时间是第一种算法的50%都不到。也算是优雅了!