本类型博客中的各算法的时间复杂度分析均为博主自己推算,本类型博客也是博主自己刷LeetCode的自己的一些总结,因此个中错误可能较多,非常欢迎各位大神在博客下方评论,请不吝赐教
一、问题
- 输入:输入一个字符串
- 输出:该字符串的最长回文子串
二、输入输出示例
示例一:
- 输入: "babad"
- 输出:"bab" 或 "aba"
- 输入:"cbbd"
- 输出:"bb"
三、解法
想法一:回味字符串必定是两个相同的字符之间的一个字符串,因此判断该字符串中所有两个相同字符之间的子串是否为回文字符串,返回最长的即可。
解法一:暴力搜索,判断任意两个相同字符之间的子串是否为回文字符串
解题思路:因为回文字符串的首尾字符必定相同,因此暴力搜索字符串中任意两个相同字符间的子串是否为回文字符串,返回最长的子串即可。
package com.happy.leetcode.p5;
public class LongestPalindromicSubstringV1 {
public static void main(String[] args) {
String s = "babad";
System.out.println(new LongestPalindromicSubstringV1().longestPalindrome(s));
}
public String longestPalindrome(String s) {
String result = "";
for(int i=0; i<s.length(); i++) {
int index = s.length();
while(index>i) {
// 从距离该字符最远距离的相同字符开始截取子串,查找回文子串
index = s.lastIndexOf(s.charAt(i), index-1);
if((index-i+1)<=result.length()) {
// 如果子串的长度小于目前已获得的最大子串,则没有必要判断它是否为回文字符串,而且该字符也没有继续判断的必要了
break;
}
String tmp = s.substring(i, index+1);
if(isPalindromic(tmp)) {
if(tmp.length()>result.length()) {
// 由于是从最远距离开始查找,所以一旦找到一个回文子串就说明是该位置字符对应的最长子串,剩余的没有必要进行查找了
result = tmp;
break;
}
}
}
}
return result;
}
/**
* 判断一个字符串是否为回文字符串
* @param s
* @return
*/
public boolean isPalindromic(String s) {
int i = -1;
if(s.length()%2==0) {
i = s.length()/2-1;
}else {
i = s.length()/2-1;
}
for(; i>=0; i--) {
if(s.charAt(i)!=s.charAt(s.length()-i-1)) {
return false;
}
}
return true;
}
}
时间复杂度分析:由于有4层遍历,第一层为对字符串所有字符的遍历,第二层为遍历当前位置字符的剩余相同字符,该查找过程内有一个遍历过程,为第三层,第四层为对回文字符串的判断,因此作者认为该解法的时间复杂度为 O(n^4),但实际仍待研究,作者尚未搞清查找过程和判断过程是嵌套关系还是并列关系,另外实际上每个字符查找的次数不一定很多,因此实际时间复杂度可能比n^4小。