1 双指针(Java实现)
解法1:双指针-左右指针(Java实现)
/*
方法2:双指针-左右指针
思路:使用双指针(左右指针)的方法判断回文字符串,可同时解决回文串长度为奇数和偶数的情况
通过遍历原字符串的各个索引(作为回文串的中心节点-向两边扩散),调用回文字符串函数,求解最大值
时间复杂度:O(n * n)
空间复杂度:O(1)常数空间
*/
class Solution {
public String longestPalindrome(String s) {
//边界条件
if(s == null || s.length() == 0) return "";
String res = "";
//遍历字符串的各个索引,作为回文串的中心节点(奇数长度和偶数长度)
for(int i = 0; i < s.length(); i++){
//长度为奇数的回文串(中心为同一个,左右指针重合)
String str1 = Palindrome(s, i, i);
//长度为偶数的回文串(中心有两个,左右指针相邻)
String str2 = Palindrome(s, i, i + 1);
res = res.length() > str1.length() ? res : str1;
res = res.length() > str2.length() ? res : str2;
}
return res;
}
//判断是否为回文字符串串
public String Palindrome(String s, int left, int right){
//防止索引越界,且两端字符相同 → 指针分别向两侧移动
while(left >= 0 && right < s.length() && (s.charAt(left) == s.charAt(right))){
left--;
right++;
}
//返回回文字符串
//注意:while循环终止条件为 left = -1 或 right = s.length()
return s.substring(left + 1, right);
}
}
2 动态规划(Java实现)
解法2:动态规划(Java实现)
/*
方法1:动态规划
思路:定义dp数组:dp[i][j]:字符串s[i...j]是否为回文字符串
状态转移:dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1]
时间复杂度:O(n * n)
空间复杂度:O(n * n) 开辟二维dp数组
类似题目:t516 最长回文子序列
动态规划(空间换时间) 时间复杂度O(n*n) 空间复杂度O(n*n)
状态:dp[i][j] 表示子串s[i..j]是否为回文子串
状态转移方程:dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1] //子串的回文性质决定整体串的回文性质
边界条件:子问题 (j-1) - (i+1) + 1 < 2时,即子串长度小于2时,无需检查子串是否回文(必回文)
初始化:dp[i][i] = true
*/
/*
class Solution {
public String longestPalindrome(String s) {
//边界条件:字符串长度为0或1
if(s == null || s.length() == 0) return "";
if(s.length() == 1) return s;
//字符串长度大于1
int maxLen = 1; //最长回文子串的长度:用于截取回文串
int n = s.length(); //字符串长度
int start = 0; //起始索引
int end = 0; //结束索引
boolean [][] dp = new boolean[n][n]; //dp状态数组
//长度为1的子串
for(int i = 0; i < n; i++){
dp[i][i] = true;
}
//长度为2的子串
for(int i = 0; i < n-1; i ++){
if(s.charAt(i) == s.charAt(i+1)){
dp[i][i+1] = true;
start = i;
maxLen = 2;
}
}
//长度大于等于3的子串
for(int k = 3; k <= n; k++){ //子串长度
for(int i = 0; i < n - k + 1; i++){ //start索引的可取范围:0 ~ n-k
int j = i + (k - 1); //end索引值: end = start + (k-1);
if(s.charAt(i) == s.charAt(j) && dp[i+1][j-1]){ //子串首尾字符相同 && 子串子问题的dp状态为true
dp[i][j] = true;
if(k > maxLen){ //满足条件的回文子串的长度k
start = i; //记录start索引
maxLen = k;
}
}
}
}
return s.substring(start, start + maxLen); //截取子串(包左不包右)
}
}
*/