归并排序总结

news2025/1/22 21:00:10

1.归并排序

归并排序的步骤如下:

①枚举中点,将区间分为左右两段;

②对左右两段区间分别排序;

        这个过程以递归的方式进行。

③合并两段区间。

        是一个模拟的过程。用两个指针分别指向左右区间,判断当前哪个数小,将小的数合并进总区间,指针后移。当指针移到某个区间的末尾,则将另一个区间的剩余部分直接接到总区间后面。

代码模板如下:

#include<iostream>
using namespace std;
const int N=1e5+10;
int n,a[N],tmp[N];
void merge_sort(int a[],int l,int r)
{
    if(l>=r) return;
    int mid=(l+r)>>1;
    merge_sort(a,l,mid);
    merge_sort(a,mid+1,r);
    int i=l,j=mid+1,k=0;
    while(i<=mid&&j<=r)
    {
        if(a[j]<=a[i]) tmp[k++]=a[j++];
        else tmp[k++]=a[i++];
    }
    while(i<=mid) tmp[k++]=a[i++];
    while(j<=r) tmp[k++]=a[j++];
    for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    merge_sort(a,1,n);
    for(int i=1;i<=n;i++) printf("%d ",a[i]);
}

2.求逆序对数量

归并排序一个很重要的作用就是用来求数组中的逆序对数量。

在归并排序过程中,当我们发现ai>aj时,所有[ai,mid]区间内的数都可以和aj构成逆序对,我们把这些数加起来,就能计算出所有的逆序对数量。

#include<iostream>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int n,a[N],tmp[N];

ll merge_sort(int a[],int l,int r)
{
    if(l>=r) return 0;
    int mid=(l+r)>>1;
    ll res=merge_sort(a,l,mid)+merge_sort(a,mid+1,r);
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r)
    {
        if(a[i]>a[j])
        {
            res+=(mid-i+1);
            tmp[k++]=a[j++];
        }
        else tmp[k++]=a[i++];
    }
    while(i<=mid) tmp[k++]=a[i++];
    while(j<=r) tmp[k++]=a[j++];
    for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
    return res;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    ll res=merge_sort(a,1,n);
    printf("%lld",res);
}

3.小朋友排队

我们可以知道,通过交换,我们每次可以最多减少1个逆序对,假设逆序对数量为k,要完成排序,我们交换的总次数最少是k次,而这个最少次数是可以达到的(在冒泡排序中就可以达到),而且在达到这个次数时,我们的交换方案是恒定的(必须按照冒泡排序的方式)。

对于某个小朋友,如果他前面有k1个比他高的小朋友,后面有k2个比他低的小朋友,要使最后小朋友的身高变为从小到大排列,那么这个小朋友至少要被交换k1+k2次。

而k1+k2的值,我们可以借助归并排序求出。

当a[i]>a[j]时,[i,mid]范围内的数都大于a[j],对于a[j]来说,有mid-i+1个逆序对,即a[j]的k1=mid-i+1;

当a[j]>=a[i]时,[mid+1,j-1]范围内的数都小于a[i],对于a[i]来说,有j-mid-1个逆序对,即a[i]的k2=j-mid-1。

#include<iostream>
using namespace std;
const int N=1e5+10;
typedef pair<int,int> PII;
typedef long long ll;
#define x first
#define y second
int n;
PII a[N],tmp[N];
ll cnt[N];
void merge_sort(PII a[],int l,int r)
{
    if(l>=r) return;
    int mid=(l+r)>>1;
    merge_sort(a,l,mid);
    merge_sort(a,mid+1,r);
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r)
    {
        if(a[i].y>a[j].y) 
        {
            cnt[a[j].x]+=(mid-i+1);
            tmp[k++]=a[j++];
        }
        else
        {
            cnt[a[i].x]+=(j-mid-1);
            tmp[k++]=a[i++];
        }
    }
    while(i<=mid) 
    {
        cnt[a[i].x]+=(r-mid);
        tmp[k++]=a[i++];
    }
    while(j<=r) 
    {
        tmp[k++]=a[j++];
    }
    for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
    {
        a[i].x=i;
        scanf("%d",&a[i].y);
    }
    merge_sort(a,1,n);
    ll res=0;
    for(int i=1;i<=n;i++) res+=(cnt[i]+1)*cnt[i]/2;
    printf("%lld",res);
}

4.火柴排队

505. 火柴排队 - AcWing题库

首先需要一点点贪心,我们可以证明出,当a、b都单调排列时,得到的距离是最小的。证明的过程是反证法,我们假设a(i)<a(i+1),b(i)>b(i+1),与a(i)<a(i+1),b(i)<b(i+1)的情况进行比较就可以很容易证明。

接下来,我们可以将问题简化,假设a数组是单调递增的,那么此时的最小交换次数就等于b的逆序对数量。我自己在这里就犯了一个小错误,到这一步,就想当然地认为最后的结果就等于b数组逆序对数量-a数组逆序对数量。其实不是,逆序对数量相等的两个数组并不是完全相同的。

我们继续往下思考。其实,我们只需要保证a、b数组中按照从小到大排序,处于一个位置的数一一对应就好了。由此,我们可以将a数组的1~n位数字映射成1~n,并将b数组中的数字按照这个映射规则映射一遍,此时情况就变成了我们上一步思考的简化情况:a数组升序排列。而b数组的数,因为使用和a数组相同的字典也映射了一遍,因此可以反映出实际中a、b数组中应对应的数的位置差距。

在映射时感觉有一个小bug,我只用a中的元素构建了映射表,但是,如果b中出现了a中没有出现的元素,我的映射会出现问题。

#include<iostream>
#include<unordered_map>
#include<algorithm>
using namespace std;
const int N=1e5+10;
const int mod=99999997;
typedef long long ll;
int a[N],b[N],tmp[N],c[2*N];
int n;
unordered_map<int,int> ha;
ll merge_sort(int a[],int l,int r)
{
    if(l>=r) return 0;
    int mid=(l+r)>>1;
    ll res=merge_sort(a,l,mid)+merge_sort(a,mid+1,r);
    res%=mod;
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r)
    {
        if(a[i]>a[j])
        {
            res+=mid-i+1;
            tmp[k++]=a[j++];
        }
        else tmp[k++]=a[i++];
    }
    while(i<=mid) 
    {
        tmp[k++]=a[i++];
    }
    while(j<=r) tmp[k++]=a[j++];
    for(int i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
    return res%mod;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int j=1;j<=n;j++) scanf("%d",&b[j]);
    int k=1;
    
    for(int i=1;i<=n;i++)
    {
        if(ha.find(a[i])==ha.end()) ha.insert({a[i],k++});
    }
    
    for(int i=1;i<=n;i++) b[i]=ha[b[i]];
    ll k2=merge_sort(b,1,n);
    printf("%lld",k2);
}

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

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

相关文章

【Linux C | 网络编程】广播概念、UDP实现广播的C语言例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

酷开科技服务升级,酷开系统给消费者更好的使用体验!

看电视的时候你是不是也会有选择困难症&#xff1f;不知道要看哪个&#xff1f;不知道如何操作&#xff1f;体验不够顺畅&#xff1f;现在&#xff0c;有了酷开系统9.2&#xff0c;这些通通不再是问题&#xff01;酷开科技&#xff0c;一直致力于服务升级&#xff0c;给消费者更…

springBoot整合Redis(三、整合Spring Cache)

缓存的框架太多了&#xff0c;各有各的优势&#xff0c;比如Redis、Memcached、Guava、Caffeine等等。 如果我们的程序想要使用缓存&#xff0c;就要与这些框架耦合。聪明的架构师已经在利用接口来降低耦合了&#xff0c;利用面向对象的抽象和多态的特性&#xff0c;做到业务代…

uniapp+vue3+vites使用lime-echart问题记录

问题记录 1.vue3使用echarts,H5和微信小程序兼容问题 1.vue3使用echarts,H5和微信小程序兼容问题 问题描述&#xff0c;正常使用echarts&#xff0c;H5正常&#xff0c;小程序报错 报错信息如下 解决方案&#xff1a; 注意要点一&#xff1a;vue3需要使用esm文件 地址&#x…

Elasticsearch:从 ES|QL 到 Python 数据帧

在我之前的文章 “Elasticsearch&#xff1a;ES|QL 查询展示”&#xff0c;我展示了如何在 Kibana 中使用 ES|QL 对索引来进行查询及统计。在很多的情况下&#xff0c;我们需要在客户端中来对数据进行查询&#xff0c;那么我们该怎么办呢&#xff1f;我们需要使用到 Elasticsea…

怎么将电脑excel文档内的数据转换为图片形式

你平时在办公室会遇到格式转换的问题吗&#xff1f;比如PDF转Word&#xff0c;WPS转PDF&#xff0c;PDF转TXT&#xff0c;图片转PDF等。边肖最近在工作过程中遇到了类似的问题。为了更方便的查看表格&#xff0c;需要将Excel表格转换成图片格式。遇到这样的问题&#xff0c;很多…

CPP编程-CPP11中的内存管理策略模型与名称空间管理探幽(时隔一年,再谈C++抽象内存模型)

CPP编程-CPP11中的内存管理策略模型与名称空间管理探幽 CPP的四大内存分区模型 在 C 中&#xff0c;**内存分区是一种模型&#xff0c;用于描述程序运行时内存的逻辑组织方式&#xff0c;但在底层操作系统中&#xff0c;并不存在严格意义上的内存分区。**操作系统通常将内存分…

计算机大数据毕业设计-基于Flask的旅游推荐可视化系统的设计与实现

基于Flask的旅游推荐可视化系统的设计与实现 编程语言&#xff1a;Python3.10 涉及技术&#xff1a;FlaskMySQL8.0Echarts 开发工具&#xff1a;PyCharm 摘要&#xff1a;以Pycharm为旅游推荐系统开发工具&#xff0c;采用B/S结构&#xff0c;使用Python语言开发旅游景点推…

【python】成功解决ModuleNotFoundError: No module named ‘tensorboardX‘

【python】成功解决ModuleNotFoundError: No module named ‘tensorboardX’ &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f…

二维码门楼牌管理系统应用场景:助力环保部门提升监管效率

文章目录 前言一、二维码门楼牌管理系统的环保应用场景二、二维码门楼牌管理系统如何助力环保监管三、二维码门楼牌管理系统与环保部门的联动效应 前言 随着城市化进程的加速&#xff0c;环保问题日益受到人们的关注。二维码门楼牌管理系统的出现&#xff0c;为环保部门提供了…

【论文阅读】DeepLab:语义图像分割与深度卷积网络,自然卷积,和完全连接的crf

【论文阅读】DeepLab:语义图像分割与深度卷积网络&#xff0c;自然卷积&#xff0c;和完全连接的crf 文章目录 【论文阅读】DeepLab:语义图像分割与深度卷积网络&#xff0c;自然卷积&#xff0c;和完全连接的crf一、介绍二、联系工作三、方法3.1 整体结构3.2 使用空间金字塔池…

机器人期刊:Science Robotics and IEEE Transactions

文章目录 1. Science Robotics (出版商 AAAS)2. IEEE Transactions on RoboticsReference1. Science Robotics (出版商 AAAS) https://www.science.org/journal/scirobotics 2. IEEE Transactions on Robotics

动手学深度学习-现代循环神经网络(GRU、LSTM、编码器-解码器等)

现代循环神经网络 上一章节&#xff08;循环神经网络&#xff09;介绍了循环神经网络的基础知识&#xff0c;这种网络可以更好的处理序列数据。我们在文本数据上实现了基于循环神经网络的语言模型&#xff0c;但是对于当今各种各样的序列学习问题&#xff0c;这些技术可能不够…

SpringBoot集成JSP和war包部署到Tomcat

SpringBoot集成JSP 加依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot…

Spring Security的API Key实现SpringBoot 接口安全

Spring Security的API Key实现SpringBoot 接口安全 Spring Security 提供了各种机制来保护我们的 REST API。其中之一是 API 密钥。API 密钥是客户端在调用 API 调用时提供的令牌。 在本教程中&#xff0c;我们将讨论如何在Spring Security中实现基于API密钥的身份验证。 API…

hyperf 二十五 数据迁移 一

教程&#xff1a;Hyperf 版本说明 一 生成迁移 php bin/hyperf.php gen:migration create_users_table 执行文件&#xff1a;Hyperf\Database\Commands\Migrations\GenMigrateCommand 功能&#xff1a;创建迁移文件 参数&#xff1a; name 文件名称 选项&#xff1a; c…

Docker连接Mysql

Docker连接mysql Docker通过云服务器&#xff0c;与本地连接 引言&#xff1a;这个东西我看狂神秒解决&#xff0c;我就试试了&#xff0c;结果G了&#xff0c;花了我两个小时&#xff0c; 希望内容能帮你解决问题 话不多说&#xff0c;直接上内容&#xff1a; navicat连接…

记一次 .NET某设备监控自动化系统 CPU爆高分析

一&#xff1a;背景 1. 讲故事 先说一下题外话&#xff0c;一个监控别人系统运行状态的程序&#xff0c;结果自己出问题了&#xff0c;有时候想一想还是挺讽刺的&#xff0c;哈哈&#xff0c;开个玩笑&#xff0c;我们回到正题&#xff0c;前些天有位朋友找到我&#xff0c;说…

redis IO多路复用模型详解

一、IO 1.1、IO模型 我们常说的IO&#xff0c;指的是文件的输入和输出 &#xff0c;但是在操作系统层面是如何定义IO的呢&#xff1f;到底什么样的过程可以叫做是一次IO呢&#xff1f; 拿一次磁盘文件读取为例&#xff0c;我们要读取的文件是存储在磁盘上的&#xff0c;我们的…

Redis的BitMap的使用

简介 Redis的Bitmap不是一个独立的数据结构类型&#xff0c;而是基于字符串&#xff08;String&#xff09;类型实现的一种功能 &#xff0c;存储的是二进制的文件&#xff0c;布隆过滤器就是基于BitMap实现的。 语句的使用 新增操作 setbit key offset value offset的首位…