添加字符判断是否为回文串

Posted on 2018-09-01 21:17  薄凉人  阅读(321)  评论(0编辑  收藏  举报

题目:给定一个字符串,问是否能通过添加一个字母将其变为回文串。

提要:所有代码皆为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;
}

这里写图片描述

有什么问题欢迎各位读者提问,谢谢!

Copyright © 2024 薄凉人
Powered by .NET 9.0 on Kubernetes