题目:
给定一个非空字符串 s
,最多删除一个字符。判断是否能成为回文字符串。
示例1:
输入: "aba"
输出: True
示例2:
输入: "abca"
输出: True
解释: 你可以删除c字符。
注意:
- 字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。
题目其实挺简单的,一开始去想符合题目要求的字符串有啥规律,走了些弯路,后面发现其实直接遍历就好了,遇到不满足回文条件的就检测是删除左边的还是删除右边的能符合条件,时间复杂度也就O(n)。
代码实现的时候出了点错误,最开始的想法是用flag来记录是否已经删除,如果删除过了按照正常回文字符串检测来。最初代码实现如下
bool validPalindrome(char * s){
int len=strlen(s);
int start=0,end=len-1,flag=0;
while(start<end){
if(s[start]!=s[end]){
if(flag==0&&s[start+1]==s[end]){
start++;
flag=1;
}
else if(flag==0&&s[start]==s[end-1]){
end--;
flag=1;
}
else
return false;
}
start++;
end--;
}
return true;
}
后面发现在测试用例中会有这样的错误,当不满足回文条件时,如果删除左边或者删除右边都暂时满足条件,但是删除右边才能使整个字符串满足回文时,我的代码就出错了。
出错测试用例
"aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga"
改错方法就是在不满足回文时必须同时检测左右,因为觉得全在一个函数里边些有点赘余,就写了个辅助函数isPalindrome只检测是否满足回文,改进后代码如下
bool isPalindrome(char *s,int start,int end){
while(start<end){
if(s[start++]!=s[end--]) return false;
}
return true;
}
bool validPalindrome(char * s){
int len=strlen(s);
int start=0,end=len-1;
while(start<end){
if(s[start]!=s[end])
return isPalindrome(s,start+1,end)||isPalindrome(s,start,end-1);
start++;
end--;
}
return true;
}
运行结果:
另外在本地调试时报了警告说strlen返回的是unsigned long long,代码应该写成如下
int len=(int)strlen(s);
LeetCode是没有警告的,也就没改了