【字符串】【贪心】【 树状数组】2193. 得到回文串的最少操作次数

news2024/9/23 1:30:30

作者推荐

视频算法专题

本文涉及知识点

字符串 贪心 树状数组 分类讨论

LeetCode2193. 得到回文串的最少操作次数

给你一个只包含小写英文字母的字符串 s 。
每一次 操作 ,你可以选择 s 中两个 相邻 的字符,并将它们交换。
请你返回将 s 变成回文串的 最少操作次数 。
注意 ,输入数据会确保 s 一定能变成一个回文串。
示例 1:
输入:s = “aabb”
输出:2
解释:
我们可以将 s 变成 2 个回文串,“abba” 和 “baab” 。

  • 我们可以通过 2 次操作得到 “abba” :“aabb” -> “abab” -> “abba” 。
  • 我们可以通过 2 次操作得到 “baab” :“aabb” -> “abab” -> “baab” 。
    因此,得到回文串的最少总操作次数为 2 。
    示例 2:
    输入:s = “letelt”
    输出:2
    解释:
    通过 2 次操作从 s 能得到回文串 “lettel” 。
    其中一种方法是:“letelt” -> “letetl” -> “lettel” 。
    其他回文串比方说 “tleelt” 也可以通过 2 次操作得到。
    可以证明少于 2 次操作,无法得到回文串。
    提示:
    1 <= s.length <= 2000
    s 只包含小写英文字母。
    s 可以通过有限次操作得到一个回文串。

贪心

s[0]和s[n-1]是第0对,s[1]和s[n-2]是第二对…
从大到小处理第i对,会让已经处理好的对,不在匹配。故只能从小到大处理。

分类讨论

任意两对x和y,有如下关系:
一,xxyy,两者相互无影响。
二, ⋯ a 个字符 x ⋯ b 个字符 y ⋯ c 个字符 y ⋯ d 个字符 x ⋯ e 个字符 ^{a个字符}_{\cdots} x ^{b个字符}_{\cdots}y ^{c个字符}_{\cdots}y ^{d个字符}_{\cdots}x ^{e个字符}_{\cdots} a个字符xb个字符yc个字符yd个字符xe个字符
先处理x,需要:a+e 在处理y,需要:a+b+d+e
先处理y:需要a+b+1+d+e+1,再处理x需要:a+e。
必须先处理x。
三, ⋯ a 个字符 x ⋯ b 个字符 y ⋯ c 个字符 x ⋯ d 个字符 y ⋯ e 个字符 ^{a个字符}_{\cdots} x ^{b个字符}_{\cdots}y ^{c个字符}_{\cdots}x ^{d个字符}_{\cdots}y ^{e个字符}_{\cdots} a个字符xb个字符yc个字符xd个字符ye个字符
先处理x: a+d+e+1,再处理y: a+b+e
线处理y: a+b+1+e 再处理x:a+d+e
结果一样:先处理谁都可以。
结果: 除非被另外一个字符包括,则可以先处理。
最左边的x,如果有多个可以匹配的x,选择最右边的x。
F o r i : 0 i < s . l e n g t h / 2 匹配 s [ i ] For\Large_{i:0}^{i < s.length/2}匹配s[i] Fori:0i<s.length/2匹配s[i]
如果s[i] 是只有一个,按就是中心。从后面处理,将s转置。
以可以忽略,留到最后处理:

	if (0 == index)
			{
				iRet += s.length()/2;
                s = s.substr(1);
				continue;
			}

代码

核心代码

class Solution {
public:
	int minMovesToMakePalindrome(string s) {
		int iRet = 0;
		while (s.length() > 2)
		{
			int index = s.find_last_of(s[0]);
			if (0 == index)
			{
				std::reverse(s.begin(), s.end());
				continue;
			}
			iRet += (s.length() - 1 - index);
			s = s.substr(1, index - 1) + s.substr(index + 1);
		}
		return iRet;
	}
};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}

}

int main()
{
	string s ;
	{
		Solution sln;
		s = "adabb";
		auto res = sln.minMovesToMakePalindrome(s);
		Assert(3, res);
	}
	
	
}

2023 年 3月版

class Solution {
public:
int minMovesToMakePalindrome(string s) {
//统计各字符出行的次数
std::unordered_map<char, int> mFreq;
for (const auto&ch : s)
{
mFreq[ch]++;
}
int iRet = 0;
//记录组间移动后各字符的位置
std::unordered_map<char, vector> mLeft, mRight;
int iLeftCnt = 0, iRightCnt = 0;
for (int i = 0; i < s.length(); i++)
{
const char& ch = s[i];
if (mLeft[ch].size() < mFreq[ch] / 2)
{
iRet += i - iLeftCnt;//组间移动
mLeft[ch].emplace_back(iLeftCnt);
iLeftCnt++;
}
else
{
mRight[ch].emplace_back(iRightCnt);
iRightCnt++;
}
}
//如果是奇数,左边末尾加上
for (auto& it : mLeft)
{
if (mFreq[it.first] & 1)
{
it.second.emplace_back(iLeftCnt++);
}
}
//vMove[i]的值是b,表示目前在i位置的字符要移动到b位置
vector vMove(iRightCnt);
for (auto it : mRight)
{
const auto& vLeft = mLeft[it.first];
for (int i = 0; i < it.second.size(); i++)
{
const int j = vLeft.size() - 1 - i;
const int iNewPos = iRightCnt -1 - vLeft[j];
vMove[it.second[i]] = iNewPos;
}
}

	//逆序对数就是组间移动数
	CTreeArr<int> tree(iRightCnt);
	for (int i = iRightCnt - 1; i >= 0; i--)
	{
		iRet += tree.Sum(vMove[i]);
		tree.Add(vMove[i], 1);
	}
	return iRet;
}

};

2023年7月版

class Solution {
public:
int minMovesToMakePalindrome(string s) {
m_c = s.length();
int iRet = 0;
for (int left = 0; left < m_c / 2; left++)
{
int right = s.length() - 1;
for (; s[right] != s[left]; right–);
if (left == right)
{
iRet += m_c / 2 - left;
}
else
{
iRet += s.length() - 1 - right;
s.erase(right, 1);
}
}
return iRet;
}
int m_c;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业
。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1502958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt5.14.2揭秘Qt与SSL/TLS的完美邂逅:打造坚不可摧的网络安全防线

引言&#xff1a; 在数字化时代&#xff0c;数据安全是每个开发者和用户都不可忽视的问题。Qt&#xff0c;作为一个强大的跨平台开发框架&#xff0c;为我们提供了丰富的网络功能&#xff0c;其中就包括了对SSL/TLS加密通信的支持。本文将带你深入了解如何在Qt中实现SSL证书认证…

【力扣白嫖日记】1174.即时食物配送II

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1174.即时食物配送II 表&#xff1a;Person 列名类型delivery_idintcustomer_idintorder_datedatecustomer_…

C# winform 重启电脑

一、重启电脑指令 windows7系统的启动文件夹为“开始菜单”——“所有程序”里面就有“启动”文件夹&#xff0c;其位置是 “C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup” 如果没有&#xff0c;则需要将其中的"administrator…

PHP storm连接阿里云服务器

阿里云开放端口 &#xff1a;1024/65535 然后宝塔 FTP 设置账户密码 和开放的文件目录 SFTP &#xff1a;账号root 密码&#xff1a;阿里云设置的密码

什么是MAE和MSE?

平均绝对误差&#xff08;Mean Absolute Error&#xff0c;MAE&#xff09;和平均方差误差&#xff08;Mean Squared Error&#xff0c;MSE&#xff09;是常用的评价回归模型性能的指标。它们用于衡量模型预测值与真实值之间的差异。 在深度学习领域&#xff0c;MAE 和 MSE 是…

Centos7安装Gogs完整教程

前言 本文章讲的是如何在Centos7下安装git服务器Gogs&#xff0c;本文参考了网络上的文章和官方文档。根据本文来操作可以完美安装Gogs&#xff0c;如果有其他问题或者看法&#xff0c;可以在评论区留下你的问题或看法。如果觉得本文对你有用&#xff0c;还请点赞和收藏一下。…

【新书推荐】17.3 字符串操作举例

本节内容&#xff1a;字符串操作举例。 ■例3&#xff1a;接收字符串去掉空格后逆向输出&#xff0c;t17-3.asm。 ■例4&#xff1a;字符串拼接&#xff0c;t17-4.asm。 ■例5&#xff1a;判断子串&#xff0c;t17-5.asm。 17.3.1 例3&#xff1a;接收字符串去掉空格后逆向输出…

【正点原子STM32探索者】CubeMX+Keil开发环境搭建

文章目录 一、简单开箱二、资料下载三、环境搭建3.1 安装Keil MDK3.2 激活Keil MDK3.3 安装STM32CubeMX3.4 安装STM32F4系列MCU的Keil支持包 四、GPIO点灯4.1 查阅开发板原理图4.2 创建STM32CubeMX项目4.3 配置系统时钟和引脚功能4.4 生成Keil项目4.5 打开Keil项目4.6 编译Keil…

回收站选址(CCF 201912-2)解题思路

分析 把x,y坐标拼接成一个字符串&#xff08;x,y&#xff09;作为Set的key&#xff0c;保存到Set中&#xff0c;遍历Set&#xff0c;取出坐标&#xff0c;然后判断上下左右四个点是否在Set中&#xff0c;如果在&#xff0c;进而判断&#xff0c;四个角是否在Set中&#xff0c;…

git学习(创建项目提交代码)

目录 操作步骤如下 1.创建项目 2.初始化项目 3.初始化项目 4.创建一个文本文件将其推送到远程仓库 5.添加到暂存区 查看提交状态 git push 返送到暂存区 git statues 7.提交 8. 返回远程仓库检查是否上传成功 操作步骤如下 git init //初始化git remote add origin ht…

《C缺陷和陷阱》-笔记(2)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、理解函数声明 1.(*(void(*)( ))0)( ); 2.signal 函数接受两个参数&#xff1a; 3.使用typedef 简化函数声明&#xff1a; 二、运算符的优先级…

uniapp踩坑之项目:uni.previewImage简易版预览单图片

主要使用uni.previewImage //html <view class"box-card" v-for"(item,index) in DataList" :key"index"><view>图片&#xff1a;</view><image :src"item.Path" tap.stop"clickImg(item.Path)">&l…

如何深度学习

信息爆炸时代&#xff0c;诞生了很多新的学习方式&#xff0c;非常轻松就能掌握知识&#xff0c;比如&#xff0c;每天听一本书&#xff0c;半个小时就能学习一本书的精华&#xff0c;比如订阅名家专栏或者课程&#xff0c;在不长的时间内内就能学到很多知识。 很多人认为这样…

HTML5页面布局

1,图文混排布局 img {float: right;}p {font-size: 32px;} <div class"sec"><img src"penguin.png" alt"penguin"><p>With no change in the rule, the more you grow the more envious you be123 123132312...</p> &l…

安全测试工具Burpsuit和OWASP ZAP使用入门指南

Burpsuit使用入门指南 安装&#xff1a; 网上有很多相关相关保姆级别教程&#xff0c;所以这里不加赘述了尽量使用java8版本&#xff0c;破解版兼容8做的比较好如果发现注册机无法打开或者能打开注册机【run】无法点击唤起软件安装&#xff0c;可以使用命令行工具 java -jar …

JavaScript 实现飞机大战

文章目录 一些关键点概览&#xff1a;核心模块的具体实现示例&#xff1a;飞机类&#xff08;Plane&#xff09;的基本结构&#xff1a;子弹类&#xff08;Bullet&#xff09;的基本结构&#xff1a;敌机类&#xff08;Enemy&#xff09;的基本结构&#xff1a; 基于前面定义的…

膜厚测量仪在半导体应用中及其重要

随着科技的不断发展&#xff0c;半导体行业已成为当今世界的核心产业之一。在这个领域中&#xff0c;半导体膜厚测量仪作为关键设备&#xff0c;其精度和可靠性对于产品质量和生产效率具有至关重要的作用。本文将详细介绍半导体膜厚测量仪的工作原理、应用领域以及其在半导体制…

SpringMVC04、Controller 及 RestFul

4、Controller 及 RestFul 4.1、控制器Controller 控制器复杂提供访问应用程序的行为&#xff0c;通常通过接口定义或注解定义两种方法实现。控制器负责解析用户的请求并将其转换为一个模型。在Spring MVC中一个控制器类可以包含多个方法在Spring MVC中&#xff0c;对于Contr…

GSM8K数据集分享

来源: AINLPer公众号&#xff08;每日干货分享&#xff01;&#xff01;&#xff09; 编辑: ShuYini 校稿: ShuYini 时间: 2024-3-3 先进的语言模型可以在许多任务上与人类表现相媲美&#xff0c;但它们仍然难以执行多步骤数学推理任务。为此OpenAI团队创建了一个高质量、语言多…

Midjourney绘图欣赏系列(八)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…