680. 验证回文字符串 Ⅱ
给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
示例 1:
输入: “aba”
输出: True
示例 2:
输入: “abca”
输出: True
解释: 你可以删除c字符。
注意:
字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。
题解:
方法一:双指针搜索与暴力
因为题目为“最多删除一个”,所以我们可以先看一下一个不删除的情况的时,他是不是一个回文字符串。
若是直接返回1,不是的话开始进行“删除”的操作。
根据暴力法,不用思考太多,直接每一个字符我们都将他删除试一试,看一看有没有行的。遍历一遍后有行的则返回1,没有则返回0.
bool validPalindrome(char * s){
int i=0,j=strlen(s)-1;
while(i<=j)
{
if(s[i]==s[j])
{
i++;
j--;
continue;
}
break;
}
if(i>=j)
{
return 1;
}
for(int k=0;k<strlen(s);k++)
{
i=0,j=strlen(s)-1;
while(i<=j)
{
if(i==k)
{
i++;
continue;
}
if(j==k)
{
j--;
continue;
}
if(s[i]==s[j])
{
i++;
j--;
continue;
}
break;
}
if(i>=j)
{
return 1;
}
}
return 0;
}
但这样会超时。
方法二:双指针搜索+贪心算法
找准贪心策略:
对于给定的一个字符串,我们可以先看一下其头部和尾部的元素是否一样,如果不一样的话,则我们首要修改的就是头部或者尾部中的一个,然后拿修改后的再进行比较,如果第一次修改后发现还是不能成为回文,则再返回第一次修改前的状态,修改另一个,再进行比对;
如果一样的话,则最外层的这两个起不到限制他成为“不是回文字符串”的作用了。所以我们可以只看里面的那些是不是回文字符串即可。
同理在我们“剥掉第一层”后,原先的第二个和倒数第二个元素成为了“最外层”的元素,所以对他们我们发现仍然满足前者的过程,所以依旧进行上述操作。
因此我们可以发现这其实是一种规律。
上代码:
bool validPalindrome(char * s){
int i=0,j=strlen(s)-1;
int k=0,temp1,temp2;//k作为修改次数的反映,temp1和2为储存原先的状态
while(i<=j)
{
if(s[i]==s[j])//相当于“剥掉”无用的元素
{
i++;
j--;
continue;
}
else if(s[i]!=s[j]&&k==0)//第一次修改
{
temp1=i;//先把原状态储存起来
temp2=j;
i++;//相当于“删除”操作
k++;
continue;
}
else if(s[i]!=s[j]&&k==1)//第二次修改
{
i=temp1;//恢复原状态
j=temp2;
j--;
k++;
continue;
}
else if(s[i]!=s[j]&&k>1)//修改后还是成不了回文
{
return 0;
}
}
return 1;
}