问题:
Longest Palindromic Substring
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
这个题是真的花了很多的时间,刚开始思路是对的,将回文字符串按中心向两侧循环读取,不相等即break,然后记录字符串和长度,依次循环,直到找到最优解。
提交的时候知道效率不高,因为未对全文同一字符做甄别处理。
代码如下:
public class Solution {
public String longestPalindrome(String s) {
char[] c = s.toCharArray();
String t = "";//最大回文字符串
String temp = "";//暂时存放回文字符串
int len = 0;//回文长度
int max = 0;//最大回文长度
int j,k;
for(int i = 0; i < c.length;i++){
j = i;
k = i;
temp = c[i] + "";
//如果未超过数组界限
while(j > 0 && k < c.length - 1){
if(c[--j] == c[++k]){
temp = c[j] + temp + c[k];
}else{
j++;
k--;
break;
}
}
len = k - j + 1;
if(max < len){
max = len;
t = temp;
}
}
return t;
}
}
第一次就错误了,因为未考虑偶数回文字符串的情况,继续处理。
public class Solution {
public String longestPalindrome(String s) {
char[] c = s.toCharArray();
//System.out.println(c.length);
String t = "";//最大回文字符串
String temp1 = "";//暂时存放回文字符串
String temp2 = "";//暂时存放回文字符串
int len = 0;//回文长度
int max = 0;//最大回文长度
int j,k;
boolean isAddI = false;
for(int i = 0; i < c.length;i++){
j = i;
k = i;
temp1 = c[i] + "";
temp2 = "";
//判断单字符情况
char tempChar = c[i];
int oneCharLen = 1;
while(j < c.length - 1 && tempChar == c[++j]){
oneCharLen++;
}
//回文字符为奇数
j = i;
while(j > 0 && k < c.length - 1){
if(c[--j] == c[++k]){
temp1 = c[j] + temp1 + c[k];
}else{
j++;
k--;
break;
}
}
len = k - j + 1;
//回文字符为偶数
j = i+1;
k = i;
while(j > 0 && k < c.length - 1){
if(c[--j] == c[++k]){
temp2 = c[j] + temp2 + c[k];
}else{
j++;
k--;
break;
}
}
//判断奇数还是偶数回文长
if(len < k - j + 1){
len = k - j + 1;
temp1 = temp2;
}
//与最大回文数比较
if(max < len){
max = len;
t = temp1;
}
//与单字符回文比较
if(max < oneCharLen){
t = "";
max = oneCharLen;
for(int m=0; m < oneCharLen;m++){
t += tempChar;
}
}
//如果是单字符,无需重复比较,直接跳到字符中间
if(oneCharLen > 4 && !isAddI){
i += oneCharLen/2 - 2;
isAddI = true;//每次i值跳转之后最少要前进两个位置
}else{
isAddI = false;
}
if(max == c.length){
break;
}
}
return t;
}
}
这一次考虑了偶数回文以及单字符的情况,如果字符在一定范围内相等,则跳转到字符中间再开始,相等于二分法,方法上效率已经不错了,但是执行上效率依然不高,。最后对执行优化,把 temp1 = c[j] + temp1 + c[k];这样的字符串操作去掉,改为jj和kk回文开始和结束的位置标记,最后一次赋值提交,这样大大优化,单次1000个ab这样的字符串可以25ms内解出,比优化之前的150ms左右的时间大大优化。
最终的代码(整体用时336ms):
public class Solution {
public String longestPalindrome(String s) {
char[] c = s.toCharArray();
//统一奇数回文串和偶数回文串
System.out.println(c.length);
String t = "";//最大回文字符串
int len = 0;//回文长度
int max = 0;//最大回文长度
int j,k;
int jj = 0,kk = 0;
char tempChar;
int oneCharLen = 1;
boolean isAddI = false;
for(int i = 0; i < c.length;i++){
j = i;
k = i;
//判断单字符情况
tempChar = c[i];
oneCharLen = 1;
while(j < c.length - 1 && tempChar == c[++j]){
oneCharLen++;
}
//System.out.println("oneCharLen-->" + oneCharLen);
//与单字符回文比较
if(max < oneCharLen){
max = oneCharLen;
jj = i;
if(tempChar == c[j])
kk = j;
else
kk = j-1;
}
//回文字符为奇数
j = i;
while(j > 0 && k < c.length - 1){
if(c[--j] != c[++k]){
j++;
k--;
break;
}
}
len = k - j + 1;
if(len > max){
max = len;
jj = j;
kk = k;
}
//回文字符为偶数
j = i+1;
k = i;
while(j > 0 && k < c.length - 1){
if(c[--j] != c[++k]){
j++;
k--;
break;
}
}
//判断长度
len = k - j + 1;
if(len > max){
max = len;
jj = j;
kk = k;
}
//如果是单字符,无需重复比较,直接跳到字符中间
if(oneCharLen > 4 && !isAddI){
i += oneCharLen/2 - 2;
isAddI = true;//每次i值跳转之后最少要前进两个位置
}else{
isAddI = false;
}
if(max == c.length){
break;
}
}
for(int i = jj; i <= kk;i++){
t += c[i];
}
return t;
}
}