题目:给定一个字符串,问是否能通过添加一个字母将其变为回文串。
提要:所有代码皆为C++语言。
看到题,首先想到如何判断回文串
注:回文串添加或删除指定字符一定还是回文串。
对于一个字符串,从左右两端开始,以此判断,直到读取超出字符串中间。
代码如下:
#include<iostream>
#include<string.h>
using namespace std;
bool JudgeReverseString(char *str)
{
//对比对应位置字符是否相同
int len = strlen(str);
for (int i = 0; i < len/2; ++i)
{
if (str[i] != str[len - i - 1])
return false;
}
return true;
}
int main()
{
char *str = (char*)malloc(100);
memset(str, 0, 10);
cin >> str;
bool result = JudgeReverseString(str);
if(result==true)
cout<<"Yes!";
else
cout<<"No!";
}
方法一(不建议,因为时间复杂度为O(n^2))
一个字符串既然能插入对应字符构成回文串,那么删掉与之对应的字符,也一定能构成回文串。
#include<iostream>
#include<string.h>
using namespace std;
//判断回文串,在基础的回文串判断方法进行改进
bool JudgeReverseString(const char *str,int len)
{
//对比对应位置字符是否相同
for (int i = 0; i < len / 2; ++i)
{
if (str[i] != str[len - i - 1])
return false;
}
return true;
}
//插入一个字符是回文串,那么删掉对应需要删除的字符则还能构成回文串
//判断删除一个字符是否还是回文串
bool DeleteCharIsReverseString(const char str[])
{
char *copy_str = (char*)malloc(strlen(str));
for (int i = 0; i<strlen(str); ++i)
{
strncpy(copy_str, str,strlen(str));
for (int j = i; j<strlen(str); ++j)
{
copy_str[j] = copy_str[j + 1];
}
if (JudgeReverseString(copy_str,strlen(str)-1) == true)
return true;
}
return false;
}
int main()
{
char *str = (char*)malloc(1000);
memset(str, 0, 1000);
while(cin >> str)
{
bool result = DeleteCharIsReverseString(str);
if (result == true)
cout << "YES"<<endl;
else
cout << "NO"<<endl;
}
return 0;
}
方法二(在方法一的思想进行改进,摘自牛客网)
链接:https://www.nowcoder.com/questionTerminal/655a43d702cd466093022383c24a38bf
来源:牛客网
增加一个是回文,那删除一个也是回文。
具体删除方式可以采取模拟的方式,头尾遍历,i,j各指向头尾,如果相同则i++,j--。如果不同则说明出现不同,需要删除某个数故x--。
然后看str[i+1]是否等于str[j],是则删除第i个;或者看str[i]是否等于str[j-1],是则删除第j个;如若都不成立,则说明两个都得删除。
当删除个数大于等于2时,跳出循环。说明要构成回文需要删除两个以上字符故NO;
删除个数小于等于1时,则说明不删除或者删除一个就能构成回文,即添加一个也能构成回文,故YES!附上AC代码
#include<iostream>
#include<string>
using namespace std;
int main() {
string str;
while (cin >> str) {
int i, l = str.length(), x = 2, j = l - 1;
for (i = 0; i<j; i++, j--)
{
if (str[i] != str[j])
{
x--;
if (str[i + 1] == str[j])
i++;
else if (str[i] == str[j - 1])
j--;
else
x--;
}
}
if (x>0)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}
方法三(采用加入字符判断)
#include<iostream>
#include<string>
using namespace std;
//判断是否是回文串,是的话返回-1,不是的话对应位置返回下标
//因为失败要返回下标,所以满足条件并没有采取返回非负值而是-1
int IsPalindromeString(string str)
{
//对比对应位置字符是否相同
int len = str.size();
for (int i = 0; i < len / 2; ++i)
{
if (str[i] != str[len - i - 1])
return i;
}
return -1;
}
bool InsertCharIsParlindromString(string str)
{
int size = str.size();
int pos = IsPalindromeString(str);
//本身不是回文串
if (pos != -1)
{
//代码思想:从不一致的位置开始,取到右边与它对应位置的子串
//在子串前面加子串的末尾值,或者在子串末尾加子串的最前值
//原因如下,符合条件的话会满足其中一个
//如果是左边缺,则子串末尾的值就是左边缺的,添回就是回文串
//如果是右边缺,则子串开始的值就是右边缺的,添回就是回文串
//右边与pos对应的位置的值 加上 pos开始,长度size-2*pos的子串
int result1 = IsPalindromeString(str[size - 1 - pos] + str.substr(pos, size - 2 * pos));
//pos开始,长度size-2*pos的子串 加上 pos位置的值
int result2 = IsPalindromeString(str.substr(pos, size - 2 * pos) + str[pos]);
if ((result1 == -1) || (result2 == -1))
return true;
else
return false;
}
//本身是回文串,添加指定字符还是回文串
else
{
return true;
}
}
int main()
{
string str;
while (cin >> str)
{
bool result = InsertCharIsParlindromString(str);
if (result == true)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}