【算法】一文搞懂归并排序

概念

归并排序利用了分治思想,将待排序的数组范围层层划分,每次划分会得到两个大小相近的区间。当无法划分时,递归结束,自下而上进行区间合并merge操作,合并操作依次比较两个区间的元素,进而使合并后的区间有序。当进行到最后一次合并区间时,我们将会得到目标范围的有序序列。这个过程如图所示。

在这里插入图片描述

由于归并排序并不是基于交换的排序算法,因此没办法做到原地in-place排序,而是需要借助一个辅助数组,以便在合并时,可以暂时存放左侧区间的元素,这样可以将经过比较得到的元素直接放入原数组的正确位置。这也是归并排序空间复杂度的主要来源。

此外,归并排序是一种稳定的排序算法。需要注意的是,在合并过程中,左区间的元素在原数组中的位置总是位于右区间元素的左边。因此,当比较两个区间的当前元素时,如果左区间的元素小于或等于右区间的元素,应优先选择左区间的元素放入结果数组。这样可以保证相等元素的相对顺序不变,从而维护算法的稳定性。(切忌漏掉等于)

递归实现

inline void merge(int *arr, int *aux, const int left, const int mid, const int right) {for (int i = left; i < mid + 1; ++i) {aux[i] = arr[i];  // * 为避免冗余拷贝,此处先将左区间移至辅助数组// * 排序时直接向arr写入数据即可,而不用最后冗余执行拷贝}int s1 = left, s2 = mid + 1, k = left;while (s1 <= mid && s2 <= right) {if (aux[s1] <= arr[s2]) { // * 请注意,为了保持排序算法稳定,这里应该是小于等于arr[k++] = aux[s1++];} else {arr[k++] = arr[s2++];}}while (s1 <= mid) {arr[k++] = aux[s1++];}while (s2 <= right) {arr[k++] = arr[s2++];}
}// * 递归版本-归并排序
// * 排序区间:[left, right)
void mergeSort(int *arr, int *aux, const int left, const int right) {if (left >= right)return;const int mid = (left + right) / 2;mergeSort(arr, aux, left, mid);mergeSort(arr, aux, mid + 1, right);merge(arr, aux, left, mid, right);
}

非递归实现

// * 迭代版本-归并排序
void mergeSort2(int *arr, int n) {int *aux = new int[n];for (int step = 1; step < n; step *= 2) { // 以循环的形式,用指针控制区间划分,逐一区间进行合并,区间范围依次倍增for (int i = 0; i < n - 1; i += step * 2) {int left = i, mid = i + step - 1, right = min(i + 2 * step - 1, n - 1);merge(arr, aux, left, mid, right);}}delete[] aux;
}

复杂度分析

时间复杂度:递归划分深度为 O ( l g n ) O(lgn) O(lgn),合并每一层的时间复杂度为 O ( n ) O(n) O(n),因此总时间为 O ( n l g n ) O(nlgn) O(nlgn)
空间复杂度: O ( n ) O(n) O(n),辅助空间必不可少。

技巧应用

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个「交易逆序对」。请设计一个程序,输入一段时间内的股票交易记录 record,返回其中存在的「交易逆序对」总数。

示例 1:
输入:record = [9, 7, 5, 4, 6]
输出:8
解释:交易中的逆序对为 (9, 7), (9, 5), (9, 4), (9, 6), (7, 5), (7, 4), (7, 6), (5, 4)

在归并排序的每一次merge操作时,我们有两个指针s1s2分别指向待合并的左右两个区间中的元素,且这两个区间的数据有两个特点,即左区间的数在原数组中一定在右区间的左侧,且左右两区间的数据各自是有序的。因此,当归并进行到arr[s1]小于arr[s2]时,假设左区间为[l, m],那么arr[s1]一定和右区间中s2及其左侧元素均构成逆序对,这个逆序对的数量为m - s1 + 1,最后我们在递归过程中将这些逆序对数目收集起来即可。

示例代码如下:

// 归并排序解法
class Solution {
private:int mergeSort(vector<int>& record, vector<int> &aux, int l, int r) {if (l >= r) return 0;int m = (l + r) / 2;// 递归int rtn = mergeSort(record, aux, l, m) + mergeSort(record, aux, m + 1, r);for (int i = l; i <= m; ++i) {aux[i] = record[i];}int s1 = l, s2 = m + 1, k = l;// 合并阶段while (s1 <= m && s2 <= r) {if (aux[s1] <= record[s2]){record[k++] = aux[s1++];} else {rtn += m - s1 + 1; // 统计逆序对数目record[k++] = record[s2++];}}while (s1 <= m) {record[k++] = aux[s1++];}while (s2 <= r) {record[k++] = record[s2++];}return rtn;}
public:int reversePairs(vector<int>& record) {if(record.empty()) return 0;vector<int> aux(record.size(), 0);return mergeSort(record, aux, 0, record.size() - 1);}
};

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn), 相较于暴力双循环的 O ( n 2 ) O(n^2) O(n2)有显著提升。
在这里插入图片描述

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

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

相关文章

【西瓜书】5.神经网络

1.概念 有监督学习正向传播&#xff1a;输入样本---输入层---各隐层---输出层反向传播&#xff1a;误差以某种形式在通过隐层向输入层逐层反转&#xff0c;并将误差分摊给各层的所有单元&#xff0c;以用于修正各层的权值激活函数&#xff1a;也叫阶跃函数&#xff0c;目的是引…

Maven 中的 classifier 属性用过没?

最近训练营有小伙伴问到松哥一个关于 Maven 依赖的问题&#xff0c;涉及到 classifier 属性&#xff0c;随机问了几个小伙伴&#xff0c;都说工作中没用到过&#xff0c;因此简单整篇文章和小伙伴们分享下。 Maven 大家日常开发应该都有使用&#xff0c;Maven 中有一个比较好玩…

最小二乘法算法(个人总结版)

最小二乘法&#xff08;Least Squares Method&#xff09;是一种通过最小化误差平方和来拟合数据的回归分析方法。它被广泛应用于线性回归、多元回归以及其他数据拟合问题中。以下是详细的教程&#xff0c;涵盖基本概念、数学推导、具体步骤和实现代码。 1. 最小二乘法基本概念…

装机必备——鲁大师安装教程

装机必备——鲁大师安装教程 软件下载 软件名称&#xff1a;鲁大师 软件语言&#xff1a;简体中文 软件大小&#xff1a;144.75M系统要求&#xff1a;Windows7或更高&#xff0c; 32/64位操作系统 硬件要求&#xff1a;CPU2GHz &#xff0c;RAM2G或更高 下载通道①迅雷云盘丨…

p5开发helloworld

注意&#xff0c;执行的时候&#xff0c;后面不用带class的后缀

C语言(字符、字符串函数)2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#xff0c;在这里撰写成文一…

Pinia(三): 了解和使用state

1.state state 就是我们要定义的数据, 如果定义 store 时传入的第二个参数是对象, 那么 state 需要是一个函数, 这个函数的返回值才是状态的初始值.这样设计的原因是为了让 Pinia 在客户端和服务端都可以工作 官方推荐使用箭头函数(()>{ })获得更好的类型推断 import { de…

最新张量补全论文收集【8篇】

目录 1、利用张量子空间先验&#xff1a;增强张量补全的核范数最小化和 2、基于可学习空间光谱变换的张量核范数多维视觉数据恢复 3、用于图像补全的增强型低秩和稀疏 Tucker 分解 4、多模态核心张量分解及其在低秩张量补全中的应用 5、 低秩张量环的噪声张量补全 6、 视…

三十四、openlayers官网示例Dynamic clusters解析——动态的聚合图层

官网demo地址&#xff1a; https://openlayers.org/en/latest/examples/clusters-dynamic.html 这篇绘制了多个聚合图层。 先初始化地图 &#xff0c;设置了地图视角的边界extent&#xff0c;限制了地图缩放的范围 initMap() {const raster new TileLayer({source: new XYZ…

JAVA流程控制break,continue,goto

1.break在任何循环语句的主体成分&#xff0c;均可用break控制循环的流程。break用于强行退出循环&#xff0c;不执行循环中剩余的语句。&#xff08;break语句也在switch语句中使用&#xff09; 如图&#xff1a;break语句强行退出循环&#xff0c;结果输出1~30便结束&#xf…

两数之和-第13届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第76讲。 两数之和&#xf…

Java面试八股之死锁和活锁的区别

死锁和活锁的区别 基本定义&#xff1a; 死锁&#xff08;Deadlock&#xff09;&#xff1a;指两个或多个线程互相等待对方释放资源&#xff0c;从而导致所有线程都无法继续执行的状态。每个线程至少持有一个资源&#xff0c;并等待另一个由其他线程持有的资源&#xff0c;形…

初始操作系统

概念&#xff1a; 1.系统资源的管理者&#xff1a;实质控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机地工作和资源的分配 2.向上层提供方便易用的服务&#xff1a;以提供给用户和其他软件方便接口和环境 封装思想&#xff1a;操作系统把一些丑…

阿里云服务器接入百度云防护后显示502原因

最近&#xff0c;发现很多使用了阿里云服务器的网站出现502的情况 经百度云防护技术排查发现阿里云机房对百度云防护的IP进行了拦截&#xff0c;原因近期可能是百度云防护的IP请求过于频繁&#xff0c;导致阿里云机房策略把百度云的IP当成了攻击IP。 解决办法是提交工单让阿里…

第三方模块的下载与安装

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在进行Python程序开发时&#xff0c;除了可以使用Python内置的标准模块外&#xff0c;还有很多第三方模块可以被我们所使用。对于这些第三方模块&…

5.31——进军MYSQL

目录 简略版&#xff1a; 详解版&#xff1a; 一. myaql概述&#xff1a; 数据库&#xff1a; 数据库管理系统&#xff1a; SQL&#xff1a; 二. masql的安装&#xff1a; 启动与停止&#xff1a; 1. MYSQL提供的命令行 2. windows提供的命令行工具 三.数据模型 …

Claude 3可使用第三方API,实现业务流程自动化

5月31日&#xff0c;著名大模型平台Anthropic宣布&#xff0c;Claude3模型可以使用第三方API和工具。 这也就是说&#xff0c;用户通过文本提问的方式就能让Claude自动执行多种任务&#xff0c;例如&#xff0c;从发票中自动提取姓名、日期、金额等&#xff0c;该功能对于开发…

DVWA靶场搭建:Apache、MySQL、PHP、DVWA

最近为了能够较为真实地学习Web渗透的各种技术&#xff0c;就想着自己搭建一个专门用于学习的Web演练平台--DVWA“靶场”。 DVWA可以进行暴力&#xff08;破解&#xff09;、命令行注入、跨站请求伪造、文件包含、文件上传、不安全的验证码、SQL注入、SQL盲注、弱会话ID、XSS漏…

批量归一化(BN)和层归一化(LN)的区别

批量归一化&#xff08;Batch Normalization, BN&#xff09;和层归一化&#xff08;Layer Normalization, LN&#xff09;是深度学习中常用的两种归一化技术&#xff0c;它们主要用于解决训练过程中的内部协变量偏移问题&#xff0c;加速模型收敛和提高稳定性。 1. 为什么需要…

基于Java的工程项目管理系统的功能与技术优势 工程管理系统源码

在当今的工程领域&#xff0c;项目管理的高效协同和信息共享是提升工作效率、降低成本的关键。本文将向您介绍一款基于Java技术构建的工程项目管理系统&#xff0c;该系统采用前后端分离的先进技术框架&#xff0c;功能全面&#xff0c;能够满足不同角色的需求&#xff0c;从项…