刷题训练之分治归并

news2024/11/20 2:24:11

> 作者:დ旧言~
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:熟练掌握分治归并算法。

> 毒鸡汤:学习,学习,再学习 ! 学,然后知不足。

> 专栏选自:刷题训练营

> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

🌟前言分析

        最早博主续写了牛客网130道题,这块的刷题是让同学们快速进入C语言,而我们学习c++已经有一段时间了,知识储备已经足够了但缺少了实战,面对这块短板博主续写刷题训练,针对性学习,把相似的题目归类,系统的刷题,而我们刷题的官网可以参考:​​​​​​

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网

⭐知识讲解

基本思想:

这个算法在我们学习数据结构中八大排序之归并,如果大家对这个算法比较陌生的话,可以参考下面这篇博客:

数据结构:手撕各种排序

特点:

我们下面题目所采用的方法都是三路划分法思想,这也和我们的标题分治不谋而合。

大致做题流程:

做题前一定要先画图,在写代码,如果能自己画出图来写代码轻松不少。

🌙topic-->1

 题目链接:1. 排序数组 - 力扣(LeetCode)

 

题目分析:

给你一个整数数组 nums,请你将该数组升序排列。(在上一个板块我们采用了快排算法解决,这里采用归并算法来解决)

算法原理:

  • 解法:采用归并算法

图解:

细节处理:

  • 递归结束标志
  • 合并数组循环结束标志
  • 处理没有遍历完的数组

代码演示:

class Solution 
{
    vector<int> tmp;
public:
    vector<int> sortArray(vector<int>& nums) 
    {
        // 开辟一个新的数组
        tmp.resize(nums.size());
        // 调用归并
        mergeSort(nums, 0, nums.size() - 1);
        // 返回
        return nums;
    }

    void mergeSort(vector<int>& nums, int left, int right)
    {
        if(left >= right) return;// 递归结束标志

        // 1.选择中间点划分区域  [left, mid] [mid+1, right]
        int mid = (left + right) >> 1;

        // 2.把左右区间排序(递归)
        mergeSort(nums, left, mid);
        mergeSort(nums, mid + 1, right);

        // 3.合并两个有序数组
        int cur1 = left, cur2 = mid + 1,i = 0;
        while(cur1 <= mid && cur2 <= right)
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] :nums[cur2++];
        // 处理没有遍历完的数组
        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= right) tmp[i++] = nums[cur2++];

        // 4.还原数组
        for(int i = left;i <= right; i++)
            nums[i] = tmp[i -left];
    }
};

🌙topic-->2

题目链接:2.LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

​ 

题目分析:

输入一段时间内的股票交易记录 record,返回其中存在的「交易逆序对」总数。

算法原理:

  • 解法:采用归并算法

图解:

代码演示:

class Solution
{
	int tmp[50010];
public:
	int reversePairs(vector<int>& nums)
	{
		return mergeSort(nums, 0, nums.size() - 1);
	}
	int mergeSort(vector<int>& nums, int left, int right)
	{
		if (left >= right) return 0;
		int ret = 0;
		// 1. 找中间点,将数组分成两部分
		int mid = (left + right) >> 1;
		// [left, mid][mid + 1, right]
		// 2. 左边的个数 + 排序 + 右边的个数 + 排序
		ret += mergeSort(nums, left, mid);
		ret += mergeSort(nums, mid + 1, right);
		// 3. ⼀左⼀右的个数
		int cur1 = left, cur2 = mid + 1, i = 0;
		while (cur1 <= mid && cur2 <= right) // 升序的时候
		{
			if (nums[cur1] <= nums[cur2])
			{
				tmp[i++] = nums[cur1++];
			}
			else
			{
				ret += mid - cur1 + 1;
				tmp[i++] = nums[cur2++];
			}
		}
		// 4. 处理⼀下排序
		while (cur1 <= mid) tmp[i++] = nums[cur1++];
		while (cur2 <= right) tmp[i++] = nums[cur2++];
		for (int j = left; j <= right; j++)
			nums[j] = tmp[j - left];
		return ret;
	}
};

🌙topic-->3

题目链接:3. 计算右侧小于当前元素的个数 - 力扣(LeetCode)

​ 

题目分析:

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元素的数量。

算法原理:

  • 解法:采用归并算法

图解:

代码演示:

class Solution
{
	vector<int> ret;
	vector<int> index; // 记录 nums 中当前元素的原始下标
	int tmpNums[500010];
	int tmpIndex[500010];
public:
	vector<int> countSmaller(vector<int>& nums)
	{
		int n = nums.size();
		ret.resize(n);
		index.resize(n);
		// 初始化⼀下 index 数组
		for (int i = 0; i < n; i++)
			index[i] = i;
			mergeSort(nums, 0, n - 1);
		return ret;
	}
	void mergeSort(vector<int>& nums, int left, int right)
	{
		if (left >= right) return;
		// 1. 根据中间元素,划分区间
		int mid = (left + right) >> 1;
		// [left, mid]  [mid + 1, right]
		// 2. 先处理左右两部分
		mergeSort(nums, left, mid);
		mergeSort(nums, mid + 1, right);
		// 3. 处理⼀左⼀右的情况
		int cur1 = left, cur2 = mid + 1, i = 0;
		while (cur1 <= mid && cur2 <= right) // 降序
		{
			if (nums[cur1] <= nums[cur2])
			{
				tmpNums[i] = nums[cur2];
				tmpIndex[i++] = index[cur2++];
			}
			else
			{
				ret[index[cur1]] += right - cur2 + 1; // 重点
				tmpNums[i] = nums[cur1];
				tmpIndex[i++] = index[cur1++];
			}
		}
		// 4. 处理剩下的排序过程
		while (cur1 <= mid)
		{
			tmpNums[i] = nums[cur1];
			tmpIndex[i++] = index[cur1++];
		}
		while (cur2 <= right)
		{
			tmpNums[i] = nums[cur2];
			tmpIndex[i++] = index[cur2++];
		}
		for (int j = left; j <= right; j++)
		{
			nums[j] = tmpNums[j - left];
				index[j] = tmpIndex[j - left];
		}
	}
};

🌙topic-->4

题目链接:4. 翻转对 - 力扣(LeetCode)

​ 

题目分析:

给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。你需要返回给定数组中的重要翻转对的数量。

算法原理:

  • 解法:采用归并算法

图解:

​​​​​​​代码演示:

class Solution
{
	int tmp[50010];
public:
	int reversePairs(vector<int>& nums)
	{
		return mergeSort(nums, 0, nums.size() - 1);
	}
	int mergeSort(vector<int>& nums, int left, int right)
	{
		if (left >= right) return 0;
		int ret = 0;
		// 1. 先根据中间元素划分区间
		int mid = (left + right) >> 1;
		// [left, mid] [mid + 1, right]
		// 2. 先计算左右两侧的翻转对
		ret += mergeSort(nums, left, mid);
		ret += mergeSort(nums, mid + 1, right);
		// 3. 先计算翻转对的数量
		int cur1 = left, cur2 = mid + 1, i = left;
		while (cur1 <= mid) // 降序的情况
		{
			while (cur2 <= right && nums[cur2] >= nums[cur1] / 2.0) cur2++;
			if (cur2 > right)
				break;
			ret += right - cur2 + 1;
			cur1++;
		}
		// 4. 合并两个有序数组
		cur1 = left, cur2 = mid + 1;
		while (cur1 <= mid && cur2 <= right)
			tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur2++] : nums[cur1++];
		while (cur1 <= mid) tmp[i++] = nums[cur1++];
		while (cur2 <= right) tmp[i++] = nums[cur2++];
		for (int j = left; j <= right; j++)
			nums[j] = tmp[j];
		return ret;
	}
};

🌟结束语

       今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

​​

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

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

相关文章

4.keepalived高可用

keepalived高可用 一、keepalived高可用介绍二、keepalived高可用设计1、两台haproxy负载均衡器配置一致2、在haproxy上分别安装keepalived3、配置keepalived实现高可用4、分别在两个调度器上查看浮动IP5、测试客户端通过浮动IP可正常访问业务6、模拟故障&#xff0c;将优先级高…

3个方法 介绍现货白银是如何操作的

很多朋友看到近期现货白银价格上涨得这么火热&#xff0c;他们也跟风入场开户&#xff0c;成为了白银投资者想去买卖白银。但是他们发现&#xff0c;看着走势涨涨跌跌&#xff0c;而自己却不会操作。下面我们就来讨论一下&#xff0c;现货白银是如何操作的。 看K线操作。我们打…

【菜狗学前端】在原生微信小程序使用腾讯地图API接口

一直想调用一下地图API接口什么的&#xff0c;刚好遇到了这个实验就浅浅研究写了一下&#xff0c;顺便总结一下给其他没太了解的人一点便利&#xff0c;希望能够对你有所帮助~ 如何引入、配置、使用、显示。 PS:要是嫌麻烦想要源码/有什么问题欢迎评论/私信&#xff0c;问题的话…

虹科案例|为什么PCAN MicroMod FD是数模信号转换的首选方案?

导读&#xff1a;精确的信号采集和转换是确保生产效率和质量的关键。虹科PCAN MicroMod FD系列模块&#xff0c;以其卓越的数模信号转换能力&#xff0c;为工程师们提供了一个强大的工具。本文将深入探讨如何通过虹科PCAN MicroMod FD系列模块&#xff0c;将模拟信号无缝转换为…

容器:现代计算的基础设施

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

15. 《C语言》——【如何动态内存开辟】

亲爱的读者&#xff0c;大家好&#xff01;我是一名正在学习编程的高校生。在这个博客里&#xff0c;我将和大家一起探讨编程技巧、分享实用工具&#xff0c;并交流学习心得。希望通过我的博客&#xff0c;你能学到有用的知识&#xff0c;提高自己的技能&#xff0c;成为一名优…

MySQL-----JOIN语句之左连接、右连接

接着上文我们将基于学生&#xff0c;课程&#xff0c;考试信息三个表对内连接的总结&#xff0c;我们再来对左右连接进行一个总结&#xff0c;三个表结构以及表内数据如下图所示&#xff1a; 左连接 为了便于展示左右连接的区别&#xff0c;我们在student表里插入了一位成员…

用英语介绍端午节,柯桥零基础英语培训

端午节 Dragon Boat Festival 中国传统节日&#xff0c;农历五月初五。相传古代诗人屈原在五月初五投江自杀&#xff0c;后人把这天作为节日纪念他。有划龙舟比赛、包粽子等风俗。 A traditional Chinese festival on the fifth day of the fifth lunar month. Legend has i…

2024苹果开发者大会:Siri 接上 ChatGPT,OpenAI苹果强强联合

一直在生成式AI战争中默默无闻的苹果终于憋不住了&#xff01; 北京时间6月11日凌晨1点&#xff0c;2024苹果WWDC全球开发者大会在苹果总部 Apple Park开幕。Day 1的发布会在介绍完各个操作系统的更新后&#xff0c;一半的时间都留给了本次WWDC的重头戏——苹果AI&#xff08;…

Windows11上安装docker(WSL2后端)和使用docker安装MySQL和达梦数据库

Windows11上安装docker&#xff08;WSL2后端&#xff09;和使用docker安装MySQL和达梦数据库 1. 操作系统环境2. 首先安装wsl2.1 关于wsl2.2 安装wsl2.3 查看可用的wsl2.4 安装ubuntu-22.042.5 查看、启动ubuntu-22.04应用2.6 上面安装开了daili2.7 wsl的更多参考 3. 下载Docke…

【图书推荐】《Spark 3.0大数据分析与挖掘:基于机器学习》

本书重点 学习Spark 3.0 ML模块的机器学习算法&#xff0c;用于大数据分析与挖掘。 内容简介 Spark作为新兴的、应用范围广泛的大数据处理开源框架&#xff0c;吸引了大量的大数据分析与挖掘从业人员进行相关内容的学习与开发&#xff0c;其中ML是Spark 3.0机器学习框架使用…

rigid_trans_object_model_3d----------对3D对象模型应用刚性3D转换

Description rigid_trans_object_model_3d对3D对象模型应用刚性3D变换&#xff0c;即旋转和平移&#xff0c;并返回转换后的3D对象模型的句柄。转换由Pose中给出的姿态来描述&#xff0c;形式如下&#xff0c;其中mcsi表示输入对象模型的坐标系&#xff0c;cst表示转换后模型的…

Vue 3与ESLint、Prettier:构建规范化的前端开发环境

title: Vue 3与ESLint、Prettier&#xff1a;构建规范化的前端开发环境 date: 2024/6/11 updated: 2024/6/11 publisher: cmdragon excerpt: 这篇文章介绍了如何在Vue 3项目中配置ESLint和Prettier以统一代码风格&#xff0c;实现代码规范性与可读性的提升。通过设置规则、解…

C++入门 string(2)

目录 string类的常用接口说明 string类对象的容量操作 size & max_size & length & capacity empty & clear reserve & resize string类对象的元素访问 at & back & front string类对象的修改操作&#xff08;字符串操作&#xff09; sub…

梯度提升树GBDT系列算法

Boosting方法的基本元素与基本流程&#x1f4ab; 在Boosting集成算法当中&#xff0c;我们逐一建立多个弱评估器&#xff08;基本是决策树&#xff09;&#xff0c;并且下一个弱评估器的建立方式依赖于上一个弱评估器的评估结果&#xff0c;最终综合多个弱评估器的结果进行输出…

启明智显工业级HMI芯片Model3A功耗特性--(以M3A 7寸触摸屏为例)

** 前言&#xff1a; ** 「Model系列」芯片是启明智显针对工业、行业以及车载产品市场推出的系列HMI芯片&#xff0c;主要应用于工业自动化、智能终端HMI、车载仪表盘、两轮车彩屏仪表、串口屏、智能中控、智能家居、充电桩显示屏、储能显示屏、工业触摸屏等领域。此系列具有…

错误代码 -2147136892如何解决

错误代码 -2147136892 在 LabVIEW 中表示无法找到 CANopen 硬件。这个错误可能是由以下几个原因引起的&#xff0c;如安装不正确、端口名称错误或硬件连接问题。以下是可能的原因和详细的解决步骤&#xff1a; 可能的原因 CANopen 硬件安装不正确 硬件可能未正确安装或连接。 …

六大维度全面焕新升级!麒麟信安服务器操作系统V3.6.1引领未来计算

昨日&#xff0c;openEuler 24.03 LTS 正式发布&#xff0c;麒麟信安作为openEuler社区重要贡献者和参与者&#xff0c;充分发挥自身在国产操作系统领域的技术优势&#xff0c;在打造安全可靠、极致体验的操作系统上与社区共同努力&#xff0c;同步推出服务器操作系统V3.6.1&am…

进口不锈钢硬密封蝶阀选型-美国品牌

进口不锈钢硬密封蝶阀的选型需要综合考虑多个因素&#xff0c;以确保阀门能够满足实际工况的需求。以下是根据参考文章中的信息&#xff0c;对进口不锈钢硬密封蝶阀选型进行的详细分点表示和归纳&#xff1a; 一、流体介质 种类&#xff1a;首先明确将要处理的流体介质种类&a…

长城汽车:坚定战略往往更难

长城汽车在2024年粤港澳大湾区车展上的表现和战略方向。 以下是对通稿中信息的深入解读&#xff1a; 1. **车展亮相的重要性**&#xff1a; - 长城汽车选择在粤港澳大湾区车展这一重要平台上展示其旗舰产品&#xff0c;这不仅是对产品实力的展示&#xff0c;也是品牌影响力提升…