题目描述
方法一:动态规划
-
定义一个二维数组dp[i][j] 来表示子串 s[i…j] (字符串s中从下标i为字符串的头到下标j位置为字符串的尾)是否为回文字符串 ,是回文字符串则dp[i][j]=true,否则dp[i][j]=false;
-
初始化表格对角线元素全为true
0 1 2 3 4 0 t 1 t 2 t 3 t 4 t
-
动态规划的核心:根据状态转移方程:
dp[i][j] = ( (s[i] == s[j]) and dp[i + 1][j - 1] )
既是当s[i] == s[j],dp[i][j]的值取决于dp[i + 1][j - 1]的值,根据这一思想,进行动态规划。
- 然后在循环遍历过程中寻找当前最长的回文字符串,并存储它的长度和开始下标
- 最后通过开始下标和长度进行截取
public class Solution {
public String longestPalindrome(String s) {
int len = s.length();
// 长度小于2的直接返回
if (len < 2) {
return s;
}
int maxLen = 1;
int begin = 0;
// dp[i][j] 表示 s[i, j](s的i到j下标组成的字符串) 是否是回文串
boolean[][] dp = new boolean[len][len];
char[] charArray = s.toCharArray();
//初始化表格对角线元素全为true
// 0 1 2 3 4
// 0 t
// 1 t
// 2 t
// 3 t
// 4 t
for (int i = 0; i < len; i++) {
dp[i][i] = true;
}
//以列为基准,依次填右上方的值
//状态转移方程:dp[i][j] = ( (s[i] == s[j]) and dp[i + 1][j - 1] )
//如果s[i] == s[j],dp[i][j]的值取决于dp[i + 1][j - 1]的值
// // 0 1 2 3 4
// 0 t
// 1 t
// 2 t
// 3 t
// 4 t
for (int j = 1; j < len; j++) {
for (int i = 0; i < j; i++) {
if (charArray[i] != charArray[j]) {
dp[i][j] = false;
} else {//j−1−(i+1)+1<2==》j-i<3 需要考虑dp[i+1][j-1]是否满足之间的字符长度大于2
if (j - i < 3) {
dp[i][j] = true;
} else {
如果s[i] == s[j],dp[i][j]的值取决于dp[i + 1][j - 1]的值
dp[i][j] = dp[i + 1][j - 1];
}
}
// 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,在遍历过程中寻找最大长度和开始的下标
if (dp[i][j] && j - i + 1 > maxLen) {
maxLen = j - i + 1;
begin = i;
}
}
}
//最后通过开始下标和长度进行截取
return s.substring(begin, begin + maxLen);
}
}
方法二:暴力求解
public class Solution {
public String longestPalindrome(String s) {
int len=s.length();
if(len<2) {
return s;
}
int maxLen=1;
int begin=0;
char[] charArray = s.toCharArray();
for (int i = 0; i < len-1; i++) {
for(int j =i+1;j<len;j++) {
if(j-i+1>maxLen&&isHuiWen(charArray, i, j)) {
maxLen++;
begin=i;
}
}
}
return s.substring(begin,begin+maxLen);
}
private boolean isHuiWen(char[] charArray, int left, int right) {
while(left<right) {
if(charArray[left]!=charArray[right]) {
return false;
}
left++;
right--;
}
return true;
}
}