Leetcode-5099. 验证回文字符串 III

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_44116998/article/details/102303558

题目描述Leetcode-2019-第 10 场双周赛第四题
给出一个字符串 s 和一个整数 k,请你帮忙判断这个字符串是不是一个「K 回文」。

所谓「K 回文」:如果可以通过从字符串中删去最多 k 个字符将其转换为回文,那么这个字符串就是一个「K 回文」。

示例
输入:s = “abcdeca”, k = 2
输出:true
解释:删除字符 “b” 和 “e”。

提示:

  • 1 <= s.length <= 1000
  • s 中只含有小写英文字母
  • 1 <= k <= s.length

思路分析
这个题在比赛中属于压轴题,困难级别,但是掌握了方法还是挺简单的。我的思路如下:
这个题和我之前做的寻找最短编辑距离的一道题有点类似(点击了解详情),这个题的思路类似,首先,我们要比较头尾,这是我们大家都知道的思路,所以我采取二维数组进行存储行表示正序的字符串,列表示逆序的字符串,如图
在这里插入图片描述
其中数字部分就是二维数组的分布。
基础弄好后,我们如何利用二维数组表示一个关键点。先拿出我的代码实现

for (i = 1; i <= len; i++)
{
	for (j = 1; j <= len; j++)
	{
	if (str[i - 1] == basestr[j - 1])
		Map[i][j] = Map[i - 1][j - 1];
	else
		Map[i][j] = Map[i - 1][j] > Map[i][j - 1] ? ( Map[i][j - 1] + 1) : ( Map[i - 1][j] + 1 );
	}
}

首先,逆序的每一行的一个字母于正序的所有字母进行比较,如图黄色部分和红色部分进行比较,如果两个字母相等,比如黄色的a和红色的a,那么Map[ 1 ] [ 1 ]就应该等于左上角Map[ 0 ] [ 0 ]的值,为什么这么做呢?原因很简单,我们会发现位于主对角线上的值都是最优解,因为主对角线是两边比较的字符串长度相等时的情况。
在这里插入图片描述
如果不相等,那么取Map左边或者上边较小值+1赋给Map [ i ] [ j ]即可
在这里插入图片描述
因为每一个小格子都是目前最优解,我们需要选取最小的即可。


代码解析

#include<iostream>
#include<cstring> 
using namespace std;
constexpr auto Maxsize = 1001;
int Map[Maxsize][Maxsize];//比较数组
int F(char str[ ],char basestr[ ], int k)
{
	int i, j,len = strlen(str);
	for (i = 1; i <= len; i++)//行
	{
		for (j = 1; j <= len; j++)//列
		{
			if (str[i - 1] == basestr[j - 1])//相等的时候取左上角Map值
				Map[i][j] = Map[i - 1][j - 1];
			else//不相等的时候取Map左边或者上边较小值+1
				Map[i][j] = Map[i - 1][j] > Map[i][j - 1] ? ( Map[i][j - 1] + 1) : ( Map[i - 1][j] + 1 );
		}
	}
	if (Map[len][len] % 2 == 0)//为偶数时,最终解为最后的一半
		return Map[len][len] / 2;
	else//为奇数时,加一
		return Map[len][len] / 2 + 1;
}
int main()
{
	char str[Maxsize],basestr[Maxsize];
	int k;
	cout << "请输入字符串:" ;
	cin >> str;
	int len = strlen(str);
	cout << "请输入判断条件 k 回文:";
	cin >> k;
	memset( Map, 0, sizeof(Map) );
	memset(basestr, 0, sizeof(basestr));
	for (int i = len; i >= 0; i--)//第一行和第一列赋初值自身的长度,很显然就是最大值
	{
		Map[0][i] = i;
		Map[i][0] = i;
	}
	for (int temp = 0; temp < len; temp++)//逆序存储字符便于判断
		basestr[temp] = str[len - temp - 1];
	if ( F(str, basestr, k) == k)
		cout << "true"<<endl;
	else
		cout << "false" << endl;
	return 0;
}

运行结果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44116998/article/details/102303558