持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情
题目
给你一个字符串 s,找到 s 中最长的回文子串。
解题思路
关键词:回文字符串;镜像相等;
关键信息:奇数偶数字符串判断;
字符串遍历解法
最简单的方式对字符串做遍历查询:遍历每个字符所有可能性。
- 从字符串第一个字符开始遍历查询,以该字符为起点向进行字符串裁剪(substring)
- 检查裁剪后字符串是否符合回文条件
- 将符合条件字符串进行比较找到最长字符串保留。
- 遍历所有情况后输出保留的最长字符串。
public boolean isPalindrome(String text){ // 检查是否是回文字符串
int i = 0,j = text.length() - 1;
while(j > i){
if(text.charAt(i) != text.charAt(j))
return false;
i++;
j--;
}
return true;
}
public String longestPalindrome(String s) {
int length = s.length();
String palindromeText = s.substring(0,1);
for(int i = 0;i < length;i++){
int right = length - 1;
while(right > i){
String temp = s.substring(i,right + 1);
if(isPalindrome(temp) && temp.length() > palindromeText.length()){
palindromeText = temp;
}
right --;
}
}
return palindromeText;
}
PS:上述算法可解决问题但会超出时间限制(算法效率过低)
通过优化算法代码跳过忽略掉后续无用遍历情况(当后续遍历字符串长度小于已知回文字符串时直接跳过即可)。
while(right > i && (right + 1 - i > palindromeText.length())) // 增加一个条件判断
中心点扩散解法
中心扩散解法以某个字符为中心向两边扩散,直到不为回文串或者到边界为止。遍历完整条字符串的扩散方法后比较得到最长的回文串即可。
- 遍历每个字符往左右做扩散查询是否为回文串
- 由于字符串可能是偶数也可能是奇数因此在做查询时需要设定以i,i以及i,i+1为初始值做两次扩散
- 例如像"abba"这种特殊字符必须依照上述方式才能检查出来
- 如上遍历所有可能存在回文串后比较得到最长回文串输出。
public String getPalindrome(String text,int left,int right){ // 检查是否是回文字符串
while(left >= 0 &&
right < text.length() &&
text.charAt(left) != text.charAt(right)){
right++;
left--;
}
return text.substring(text,right+ 1,left);
}
public String longestPalindrome(String s) {
int len = s.length();
if (len < 2) {
return s;
}
int maxLen = 1;
String res = s.substring(0, 1);
for (int i = 0; i < len - 1; i++) {
String oddStr = centerSpread(s, i, i);
String evenStr = centerSpread(s, i, i + 1);
String maxLenStr = oddStr.length() > evenStr.length() ? oddStr : evenStr;
if (maxLenStr.length() > maxLen) {
maxLen = maxLenStr.length();
res = maxLenStr;
}
}
return res;
}
参考
- 来源:力扣(LeetCode)