按顺序,找出所有子串并判断比较
class Solution {
public String longestPalindrome(String s) {
int max = 0;//记录 最长回文子列的 长度
String str = null;//记录 最长回文子列
for (int i = 0; i < s.length(); i++) {
for (int j = i + 1; j <= s.length(); j++) {
int len = j - i;//记录 当前子列的 长度
String curr = s.substring(i, j);//记录 当前子列; substring左闭右开
if (isPalindrome(curr)){
if (len > max){
max = len;
str = curr;
}
}
}
}
return str;
}
private boolean isPalindrome(String s){
for (int i = 0; i < s.length() / 2; i++) {
if(s.charAt(i) != s.charAt(s.length() - 1 - i)){
return false;
}
}
return true;
}
}
可以通过测试用例,但是会超出时间限制
时间复杂度 O ( n 3 ) O(n^3) O(n3)
空间复杂度 O ( 1 ) O(1) O(1)
大致思路就是选一个字符,然后向两边找,判断是否组成一个回文字符串
例如 bcba,以c为单个中心点,即search(“bcba”, 1, 1),发现s.charAt(0)==s.charAt(2),记录下来,最后得到最长子串就是bcb
需要注意的是,单个索引为中心点(找到的子串长度为奇数)和两个索引为中心点(找到的子串长度为偶数)的情况都要查找
class Solution {
public String longestPalindrome(String s) {
if (s.isEmpty()){
return null;
}
if (s.length() == 1){
return s;
}
String str = s.substring(0,1);//记录 最长回文子列
for (int i = 0; i < s.length(); i++) {
String tmp = search(s, i, i);
if (tmp.length() > str.length()){
str = tmp;
}
tmp = search(s, i, i + 1);
if (tmp.length() > str.length()){
str = tmp;
}
}
return str;
}
private String search(String s, int begin, int end){
while(begin >= 0 && end < s.length() && s.charAt(begin) == s.charAt(end)){
begin--;
end++;
}
return s.substring(begin + 1, end);
}
}
时间复杂度 O ( n 2 ) O(n^2) O(n2)
空间复杂度 O ( 1 ) O(1) O(1)
s [ i , j ] s[i,j] s[i,j]:代表字符串 s s s 从索引 i i i 到索引 j j j 处的子串
d p [ i ] [ j ] = { 1 , s [ i , j ] 为回文子串 0 , i > j 即 s [ i , j ] 不存在或者 s [ i , j ] 不是回文子串 dp[i][j]=\begin{cases}1,s[i,j]为回文子串\\0,i>j即s[i,j]不存在或者s[i,j]不是回文子串\end{cases} dp[i][j]={1,s[i,j]为回文子串0,i>j即s[i,j]不存在或者s[i,j]不是回文子串
使用动态规划就是为了利用过去已经计算得到的信息,即 d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] ∧ ( s i = = s j ) dp[i][j]=dp[i+1][j-1]\land(s_i==s_j) dp[i][j]=dp[i+1][j−1]∧(si==sj)
例如basbbs
, d p [ 3 ] [ 4 ] = 1 dp[3][4]=1 dp[3][4]=1 并且 字符串s 在索引2 和 索引5 处的字符相同( s 2 = = s 5 s_2==s_5 s2==s5),那么 d p [ 2 ] [ 5 ] = 1 dp[2][5]=1 dp[2][5]=1,即 s [ 2 , 5 ] s[2,5] s[2,5]是回文子串。
需要注意边界条件,当子串为1个字符时,就是回文的;2个字符时,只要相同,就是回文
class Solution {
public static String longestPalindrome(String s) {
int len = s.length();//字符串长度
if(len <= 1)
return s;
int max = 0;//记录 最长子串的 长度
String str = s.substring(0, 1);//记录 最长子串
int[][] dp = new int[len][len];
//初始化,单个字符就是回文子串
for (int i = 0; i < len; i++) {
dp[i][i] = 1;
}
//初始化,两个字符如果相同就是回文
for (int i = 0; i < len - 1; i++) {
if (s.charAt(i) == s.charAt(i + 1)){
dp[i][i+1] = 1;
str = s.substring(i, i + 2);
}
}
//外层循环控制子串的长度,因为长度为1和2的已经在上面初始完成,所以从长度3开始
for (int l = 3; l <= len; l++) {
//控制子串的左边界,为了防止右边界j越界,用 i < len - l 控制
for (int i = 0; i <= len - l; i++) {
//右边界j根据 j-i+1=l 可以计算得到 j=l+i-1
int j = l + i - 1;//右边界
//当S_i==S_j时,dp[i][j]是否为1就由dp[i + 1][j - 1]决定
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = dp[i + 1][j - 1];
}else{
//不等时,s[i,j]不是回文子串,则dp[i][j]=0
dp[i][j] = 0;
}
if(dp[i][j] == 1 && j - i + 1 > max){
max = j - i + 1;
str = s.substring(i, j + 1);
}
}
}
return str;
}
}
给你一个字符串 s
,找到 s
中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母组成