思路1
失败思路
希望通过双指针,O(n)的时间复杂度得到回文子串,但是仅仅能通过不到50%的测试样例。
写的还是挺简洁的,但是问题出现在"abdbab"时,无法给出最长回文子串"bab"。原因在于,两侧指针只有向中间靠拢的过程,而没有回退到原来位置的过程,指针在中间位置的"db"相遇。
public static String longestPalindrome(String s) {
String str = "";
int n = s.length();
if (n != 0)
{
int p1 = 0, p2 = n-1;
int pp1 = -1, pp2 = -1;
while (true)
{
while (p1 < p2)
{
if (s.charAt(p1) == s.charAt(p2))
{
if (pp1 == -1 && pp2 == -1)
{
pp1 = p1;
pp2 = p2;
}
p1++;
p2--;
}
else
break;
}
//该子串为回文字符串
if (p1 >= p2 && pp1 != -1 && pp2 != -1)
return s.substring(pp1, pp2+1);
if (p1 >= p2 && pp1 == -1 && pp2 == -1)
return s.substring(0, 1);
//由于有不相等的字符退出,记录新的始末位置
//只能找到右侧的回文子串
//如果更换两个循环的顺序,则可以找到左侧的子串
pp1 = -1;
pp2 = -1;
while (s.charAt(p1) != s.charAt(p2) && p1 < p2)
p1++;
while (s.charAt(p1) != s.charAt(p2) && p1 < p2)
p2--;
}
}
return str;
}
思路2
中心扩展算法
总时间复杂度较高,为O(n2),空间复杂度为O(1)。
这里要注意边界条件的判断。
public static String longestPalindrome3(String s) {
String ret = "";
int n = s.length();
int[] a1;
int[] a2;
int[] a3;
int[] tmp;
int[] MostTmp = {
-1, -1};
if (n != 0)
{
for (int i = 0; i < n; i++)
{
a1 = getRoundCenter(s, i);
a2 = getRoundLeft(s, i);
a3 = getRoundRight(s, i);
tmp = getMaxRange(a1, getMaxRange(a2, a3)); //当前位置的最大范围数组
if (tmp[1] - tmp[0] >= MostTmp[1] - MostTmp[0])
MostTmp = tmp;
}
ret = s.substring(MostTmp[0], MostTmp[1]+1);
}
return ret;
}
public static int[] getRoundCenter(String s, int pos) {
int[] ret = {
-1, -1};
int n = s.length();
if (n >= 0)
{
int i = pos, j = pos; //i向左移,j向右移
// 可能是因为字符不同退出的,也可能超过边界退出的
// 这两种情况,归并为相同类型。
while (i >= 0 && j < n && s.charAt(i) == s.charAt(j))
{
if (s.charAt(i) == s.charAt(j))
{
i--;
j++;
}
else
break;
}
ret[0] = i+1;
ret[1] = j-1;
}
return ret;
}
public static int[] getRoundLeft(String s, int pos) {
int[] ret = {
-1, -1};
int n = s.length();
if (n >= 0)
{
int i = pos, j = pos+1;
int flag = -1;
while (i >= 0 && j < n)
{
if (s.charAt(i) == s.charAt(j))
{
flag = 1;
i--;
j++;
}
else
break;
}
if (flag == 1)
{
ret[0] = i+1;
ret[1] = j-1;
}
else
{
ret[0] = i;
ret[1] = i;
}
}
return ret;
}
public static int[] getRoundRight(String s, int pos) {
int[] ret = {
-1, -1};
int n = s.length();
if (n >= 0)
{
int i = pos-1, j = pos;
int flag = -1;
while (i >= 0 && j < n)
{
if (s.charAt(i) == s.charAt(j))
{
flag = 1;
i--;
j++;
}
else
break;
}
if (flag == 1)
{
ret[0] = i+1;
ret[1] = j-1;
}
else
{
ret[0] = j;
ret[1] = j;
}
}
return ret;
}
public static int[] getMaxRange(int[] a, int[] b)
{
int r1 = a[1] - a[0];
int r2 = b[1] - b[0];
if (r1 > r2)
return a;
return b;
}