题目出处:https://leetcode.com/problems/longest-palindromic-substring/
回文字符串: 简单点说就是字符串反转(reverse)后的结果还是自己。如"abcba", "abccba", 返转后的结果是一样的。最简单的回文字符串是空字符串及长度为1的字符串。
题目要求,给一个字符, 可以假设最大长度的1000.查找最大回文子字符串。并返回一个。
解决方法:
- 遍历字符串
- 假设当前位置就做为回文字符串的中心。求出其回文字符串的长度。
- 与已经查找的最大长度比较,记录两者最大值,作为当前最大长度值。
- 直到最后
感想:
以前写过一个实现,今天再看时居然没看懂,只知道大概怎么做的,处理的细节没怎么弄明白。 后面会符上代码,有兴趣的可以研究下
今天决定再写一个版本,思路一样,可代码超简单,也更清晰。
看着原来的代码,想着以前写着肯定很纠结, 这再一次让我明白:大道至简。如果事情太过纠结,那肯定是哪里出问题了!
算法版本:
string longestPalindrome(string s) {
if(s.length() <= 1)return s;
int maxLen = 1, start = 0;
int index = 0;
while(index+1 < s.length()){
//查找第一个不等于当前的字符
int i = index-1, j = index+1;
while(s[j]== s[index]) j++;
index = j;//更新下一次检查的位置
while(j < s.length() && i >= 0 && s[j]== s[i]){j++; i--;}
int len = j-i -1;//当前回文长度
if(len > maxLen){ maxLen = len; start = i+1;}
//判断后面是否还有没有必要遍历
if(index + maxLen/2 > s.length())break;
}
return s.substr(start, maxLen);
}
以前的版本
string longestPalindrome_1(string s) {
if(s.length() <= 1) return s;
int lastMid = 0;
int lastlen = 0;
int mid = 0;
int single = 1;
int length1 = 0;
int length2 = 0;
for(int i = 1; i < s.length(); i++){
// cout<< " i:" << i << " item: "<< s[i] << " mid:" << mid << " single:" << single <<endl;
int oppoIndex = mid - (i - mid);
if((single & 0x01) == 0x01){ //check single
if(oppoIndex < 0 || s[oppoIndex] != s[i]){
single &= 0x02;
length1 = (i - mid)*2 -1;
}
}
if((single & 0x02) == 0x02){ //check single = 0x02
oppoIndex -= 1;
if(oppoIndex < 0 || s[oppoIndex] != s[i]){
single &= 0x01;
length2 = (i - mid)*2;
}
}
if(single != 0) continue;
// cout<< " length1:" << length1 << " length2: "<< length2 <<endl;
int length = length1 > length2 ? length1 : length2;
length2 = 0;
length1 = 0;
//check max
if(length > lastlen){
lastlen = length;
lastMid = mid;
}
//check single = 0x01
for(int j = mid+1; j <= i; j++){
// cout<< "mid: " << mid << " j: " << j <<endl;
//check single 1 is ok
bool ok = true;
for(int k = 0; k <= i-j; k++){
if(s[j-k] != s[j+k]){
ok = false;
break;
}
}
if(ok){
mid = j;
single |= 1;
}
//check single 2 is ok
bool ok1= (s[j] == s[j-1]);
if(ok1){
for(int k = 0; k <= i-j; k++){
if(s[j-k-1] != s[j+k]){
ok1 = false;
break;
}
}
if(ok1){
mid = j;
single |= 0x02;
}
}
if(ok || ok1) break;
}
}
// cout<< "mid: " << mid << " single:" << single << " len:" << s.length()-mid << endl;
if((single & 0x01) == 0x01)
length1 = (s.length()-mid)*2 - 1;
if((single & 0x02) == 0x02)
length2 = (s.length() - mid)*2;
int length = length1 > length2 ? length1 : length2;
if(length1 > lastlen){
return s.substr(mid - (s.length()-mid) + 1);
}
if(length2 > lastlen){
return s.substr(mid - (s.length()-mid));
}
// cout<< "lastMid: " << lastMid << " lastlen:" << lastlen << endl;
return s.substr(lastMid-lastlen/2, lastlen);
}