作者 : XiaXinyu
日期 :2021-09-25
题目
理解
在给定字符串种找到满足是回文字符串到最长子串
题解1(朴素做法)
最直观的思路就是枚举出所有子串,并对每个字串进行判断,如果是回文字符串且比当前ans值大,就更新ans
代码
class Solution{
public String longestPalindrome(String s) {
int n = s.length();
String ans = "";
for(int i = 0;i < n;i ++)
for(int j = 0;j < n;j ++)
{
if(is_hw(s,i,j) && ans.length() < j - i + 1)
ans = s.substring(i,j + 1);
}
return ans;
}
public boolean is_hw(String s,int i,int j){
while(i < j){
if(s.charAt(i) != s.charAt(j)) return false;
i ++;
j --;
}
return true;
}
}
时间复杂度
:O(n^3) 两层for循环枚举出所有子串,一层while循环判断是否是回文字符串
空间复杂度
:O(1)
题解2(朴素做法优化——中心扩散法)
题解一的朴素做法时间复杂度太高,肯定是不能AC了,是不是有办法可以降低时间复杂度呢?
采用中心扩散法可以将时间复杂度从O(n3)降低到O(n2)
从头到尾遍历字符串,从当前遍历到的字符向两边扩散即可
这种做法的思路很简单,注意一些代码上的实现细节就行了
直接上代码
class Solution{
public String longestPalindrome(String S){
int maxLen = 0; //存储回文字符串最大长度
int start = 0; //存储最长回文字符串的起始位置
for(int i = 0;i < S.length();i ++){
int left = i - 1;
int right = i + 1; //left和right分别为临时回文字符串的左右边界,这里为开区间!!!
int currentLen = 1; // 存储临时回文字符串长度,因为一个字符是一定是回文字符串,所以初始化为1而不是0
//前两个while循环是为了找出与当前遍历字符相同的字符并且向两边扩散,
//因为相同的字符串一定是回文字符串!!!
while(left >= 0 && S.charAt(left) == S.charAt(i)){
currentLen ++;
left --;
}
while(right < S.length() && S.charAt(right) == S.charAt(i)){
currentLen ++;
right ++;
}
//这个while循环根据左右字符是否相等进行扩散
while(right < S.length() && left >= 0 && S.charAt(right) == S.charAt(left)){
currentLen += 2;
left --;
right ++;
}
if(currentLen > maxLen){ //如果当前回文字符串长度大于maxLen就更新maxLen以及start
maxLen = currentLen;
start = left + 1;
}
}
String ans = S.substring(start,start + maxLen);
return ans;
}
}
时间复杂度
:O(n^2) 只用了两层循环
空间复杂度
:O(1)