1. 程式人生 > >插入字元判斷是否構成迴文串(三種方法)

插入字元判斷是否構成迴文串(三種方法)

題目:給定一個字串,問是否能通過新增一個字母將其變為迴文串。

提要:所有程式碼皆為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;
}

這裡寫圖片描述

有什麼問題歡迎各位讀者提問,謝謝!