给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
来源:力扣(LeetCode)
链接: 题目链接
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法
暴力解法
思路:从长到短 列举出所有的子串找到第一个符合回文的子串就是最长的子串
- 从长到短子串的列举:
+ 长度为n的字符串
它的子串:
长度为n-i的子串 i个! 从长到短一次列举
下面展示一些
` for (int i = s.length(); i>0 ; i--) {
for (int j = 0; j <= s.length()-i ; j++) {
String ns = s.substring(j,i+j);
System.out.println(ns);
}
}`
// // //暴力解法
public static String longestPalindrome1(String s) {
//获取最长子串
for (int i = s.length(); i>0 ; i--) {
for (int j = 0; j <= s.length()-i ; j++) {
String ns = s.substring(j,i+j);
System.out.println(ns);
//从头部尾部开始避开判断是否为会问
for (int k = 0; k < ns.length(); k++) {
if(ns.charAt(k)==ns.charAt(ns.length()-1-k)) {
//如果比较到最中间说明为回文
if(k==(ns.length()-1)/2) {
return ns;
}
}else {//如果有不相等的直接脱出循环
break;
}
}
}
}
//如果没有找到返回空
return "";
}
时间复杂度o(n3 )
动态规划
思路: 将问题简化为有小到大的问题 ,从a是否为回文问题,到判断a回文a、a回文b是否为回文;
在字符串中起点为i终点为j的为回文 i+1 ,j+1必为回文, 这样就可以减少每个字符都要判断是否为回文,
P[i, j] = false:表示子串[i, j]不是回文串;
P[i, j] = true:表示子串[i, j]是回文串。
当且仅当P[i+1, j-1] = true && (s[i] == s[j])否则p[i,j] =false;
// // //动态规划
public static String longestPalindrome2(String s) {
//如果字符串不符合直接返回空
if(s.length()<=0||s==null) {
return "";
}
int len = s.length();
//回文开始的下标
int start = 0;
//回文的长度
int maxLength = 1;
boolean dp[][] = new boolean[len][len];
//初始化 动态数组
for(int i = 0 ;i < len-1;i ++) {
//初始化长度为1 一个字符 一定为回文
dp[i][i] = true;
//如果长度为2的为回文 则必为两个相等的字符
if(i<len-1 && s.charAt(i)==s.charAt(i+1)) {
dp[i][i+1] = true;
start = i;
maxLength = 2;
}
}
/**
* 相比暴力
* 减少了 每次获取到子串 循环判断是否为回文
* 子串长度从小到大 起点为i终点为j的为回文 i+1 ,j+1必为回文
*
*/
for(int strlen = 3 ;strlen <= len;strlen ++) {
for(int i=0;i<=len-strlen;i++) {
int j = i+strlen-1; //结束的位置
//只有子串为回文 1,j才有可能为回文
if(dp[i+1][j-1] && s.charAt(i)==s.charAt(j)){
dp[i][j] = true;
start = i; //记录回文的起始位置
maxLength = strlen; //最大长度
}
}
}
return s.substring(start,maxLength+start);
}
时间复杂度o(n2 ) 空间复杂度o(n2 )
其他方法后续补充。。。。