要求:求字符串中的最长回文串
回文:关于中间字符对称的文法,如 “aba”、“abba”
- 解法一 暴力求解
分析:先找到该字符串的最长字符字串,然后判断其是否为回文,如果不是,则寻找次长字符字串,继续判断是否为回文…知道找到是回文的字符字串,然会将其返回。
下面给出代码
public static String longestPalindromicSubstring(String s) {
// 如果字符串的长度小于等于1,就直接返回字符串
if(s.length() <= 1) {
return s;
}
for(int i = s.length(); i > 1; i--) {
for(int j = 0; j <= s.length() - i; j++) {
String sub = s.substring( j, i + j);
// count用来判断是否为回文
int count = 0;
for(int k = 0; k < sub.length()/2; k++) {
if(sub.charAt(k) == sub.charAt(sub.length() - k - 1))
count++;
}
// 如果count与sub.length()/2 相等,就说明这是回文字符串
if(count == sub.length()/2) {
return sub;
}
}
}
// 不存在回文字符串
return "无回文字符串";
}
总结:
(1)首先一定要考虑周全,当字符串的长度小于一时,就直接返回该字符串;
(2)该算法的时间复杂度为O(n三次方);
(3)这里寻找最长的子字符串的代码很有参考以及,需要明白两个for循环的条件中是否需要添加等于号。
- 解法二 中心拓展
分析:依次遍历字符串中每一个字母,以这个字母为中心(单核),或以这个字母和它右边的字母为核心(双核),然后对比这个中心左边和右边的字符是否相等,相等的话,就分别向左边右边移一位。不等的话,就以下一个字母为中心,重复上述操作。
下面给出代码
public String longestPalindrome(String s) {
if(s ==null || s.length() < 1) return "";
int start = 0, end = 0;
for(int i = 0; i < s.length(); i++){
int len1 = expandAroundCenter( s, i, i);
int len2 = expandAroundCenter( s, i, i+1);
int len = Math.max(len1, len2);
if(len > end - start){
start = i - (len -1)/2;
end = i + len/2; // 这里注意单核和双核的区别 双核的长度为偶数
}
}
return s.substring(start, end + 1);
}
public int expandAroundCenter(String s, int i ,int j){
int left = i, right = j;
while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
left--;
right++;
}
return right - left - 1;
}
总结:
(1)时间复杂度:O(n²),依次遍历花费O(n)time,从中心扩展也需要花费O(n)time。
(2)这里需要注意end值的更新,单核双核对start值的更新不影响,但对start的值更新有很大的影响。当为双核时,返回来的回文字串为偶数,此时以i为中心,其实对于双核来说,i+1也为中心,在计算end的值时,需要考虑到这一点。
- 解法3 Manacher算法
不是很理解,以后有时间好好研究。