问题描述:给你一个字符串 s
,找到 s
中最长的回文子串。
简单分析:
回文子串的要求是以某个点为中心左右两边的字符是一样的,这样对字符串中任意一个位置{i},只需要判断{i}左右两边的字符是否一样就能算出{i}位置的半径R[i]。文中为了排除奇偶性的干扰,对字符串做了加工,所以过程分为一下三部:
- 修正数据,排除奇偶性的干扰
- 计算每个位置的半径,并取其中的最大值
- 过滤数据,组装最终的结果。
备注:
翻阅了其他题解,我的解题思路应该属于中心扩展算法,时间复杂度是O()。另外有Manacher 算法(马拉车算法)达到了O(n),确实厉害,大家可以搜索学习下。
编码
class Solution {
public String longestPalindrome(String s) {
if (s==null || s.length() < 2){
return s;
}
// 修正数据,不考虑奇偶性
char fixArr[] = new char[s.length() * 2 + 1];
for (int i = 0; i < s.length(); i++) {
fixArr[2 * i] = '#';
fixArr[2 * i + 1] = s.charAt(i);
}
fixArr[s.length() * 2 ] ='#';
// 查找最长半径
int longest = 0, index = 0;
for (int i = 0; i < fixArr.length; i++) {
int radius = radius(fixArr, i);
if (radius > longest){
longest = radius;
index = i;
}
}
// 返回数据
StringBuilder builder = new StringBuilder() ;
for (int i = index - longest; i <= index + longest; i++) {
if (fixArr[i] != '#'){
builder.append(fixArr[i]);
}
}
return builder.toString();
}
// 计算子串半径
private int radius(char fixArr[], int index){
int radius = 0;
do {
int left = index - radius - 1;
if (left < 0)
break;
int right = index + radius + 1;
if (right >= fixArr.length)
break;
if (fixArr[right] != fixArr[left])
break;
radius ++;
} while (true);
return radius;
}
}