昨天做了Leetcode上的第5题,求一串字符串的最长回文子串,刚开始自己想了一种方式,本来以为挺简单的,但是经过了一个多小时的努力,终于发现了自己的错误,思路是错的,然后参考了网络上的答案,最终写出来了:
O(n^2)时间复杂度方法——从中心向外扩散
1.思想:
1)将子串分为单核和双核的情况,单核即指子串长度为奇数,双核则为偶数;
2)遍历每个除最后一个位置的字符index(字符位置),单核:初始low = 初始high = index,low和high均不超过原字符串的下限和上限;判断low和high处的字符是否相等,相等则low++、high++(双核:初始high = 初始low+1 = index + 1);
3)每次low与high处的字符相等时,都将当前最长的回文子串长度与high-low+1比较。后者大时,将最长的回文子串改为low与high之间的;
4)重复执行2)、3),直至high-low+1 等于原字符串长度或者遍历到最后一个字符,取当前截取到的回文子串,该子串即为最长的回文子串。
2.时间复杂度解释:
遍历字符:一层循环、O(n-1);
找以当前字符为中心的最长回文子串:嵌套两个独立循环、O(2n*(n-1)) = O(n^2)。
具体实现的java代码如下:
private int maxLen = 0;
String str = "";
// 该算法是用来求一个字符串的最长回文字符串子串
public String longestPalindrome(String s) {
if (s.length() < 2) {
return s;
}
for (int i = 0; i < s.length(); i++) {
findLongestPalindrome(s, i, i);
findLongestPalindrome(s, i, i + 1);
}
return str;
}
public void findLongestPalindrome(String s, int low, int high) {
while (low >= 0 && high < s.length() && s.charAt(low) == s.charAt(high)) {
low--;
high++;
}
if (high - low - 1 > maxLen) {
maxLen = high - low - 1;
str = s.substring(low + 1, high);
}
}
上面需要注意的一点是:在findLongestPalindrome函数里,当我们进行循环的时候,这个函数的while循环结束的时候,low在在要截取字符的左边位置,而high在要截图字符的右边位置,所以才有了str = s.substring(low + 1, high);这句代码。
网上还有一种解决方案,更快,但是感觉那个好难,目前还没法看懂,留着以后再看吧,这里附上我的参考连接:参考链接1
参考链接2