插入字元判斷是否構成迴文串(三種方法)
阿新 • • 發佈:2019-01-05
題目:給定一個字串,問是否能通過新增一個字母將其變為迴文串。
提要:所有程式碼皆為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;
}