菜鸡每日一题系列打卡5天
每天一道算法题目
小伙伴们一起留言打卡
坚持就是胜利,我们一起努力!
题目描述(引自LeetCode)
给定一个字符串s,找到s中最长的回文子串。你可以假设s的最大长度为1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
题目分析
寻找回文子串比较容易想到的办法是中心扩展的办法,根据回文子串的特点,回文中心即对称中心,因此,寻找回文子串可以针对每个回文中心向两侧扩展,像这样的回文中心有2n - 1个,根据这一思想,可以得到一个相对比较高效的算法。但事实上,该方法并不是时间复杂度最低的解法,还有一种被称为Manacher算法的解法,可以在线性时间内求解,该算法的思想是通过引入标记分隔符,将奇数长度的回文子串和偶数长度的回文子串统一转化为奇数长度进行处理,并用辅助数组减少重复对比次数,从而达到O(n)时间复杂度的理论下界。其中,需要注意的是,标记分隔符需要选取字符串中不包含的字符。鉴于该方法分隔符选取的局限性,本文最终采取的是中心扩展的方法进行实现的。对Manacher算法感兴趣的小伙伴可以自行通过搜索引擎进行深入研究,过程会非常有趣哦!
代码实现
class Solution {
public String longestPalindrome(String s) {
// 特殊情况处理
if (s == null || s.length() == 0) {
return "";
}
// 在循环过程中,以每个位置为中心进行扩展
int start = 0;
int end = 0;
for (int i = 0; i < s.length(); i++) {
int length = Math.max(getPalindromeLength(s, i, i), getPalindromeLength(s, i, i + 1));
if (length > end - start) {
start = i - (length - 1) / 2;
end = i + length / 2;
}
}
return s.substring(start, end + 1);
}
// 获取以当前位置为中心的最长回文子串长度
private int getPalindromeLength(String s, int start, int end) {
// 特殊情况处理
if (s == null || s.length() == 0) {
return 0;
}
// 回文条件判断
while (start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)) {
start--;
end++;
}
return end - start - 1;
}
}
代码分析
针对代码进行分析,围绕一个中心进行扩展的时间复杂度是O(n),一共有2n - 1个这样的中心,因此时间复杂度是O(n^2);空间方面只需要申请固定的几个临时变量,因此空间复杂度是O(1)。
执行结果
关注公众号有理想的菜鸡,和菜鸡一起打卡吧!点个在看让更多小伙伴看到。