逆序对的数量(归并排序的深度理解)

2023-10-27

逆序对的数量问题

问题详情

给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。

逆序对的定义如下:对于数列的第 i 个和第 j个元素,如果满足 i<j 且 a[i]>a[j],则其为一个逆序对;否则不是。

输入格式
第一行包含整数 n,表示数列的长度。

第二行包含 n 个整数,表示整个数列。

输出格式
输出一个整数,表示逆序对的个数。

数据范围
1≤n≤100000
数列中的元素的取值范围 [1,109]

输入样例:
6
2 3 4 5 6 1
输出样例:
5

问题分析

归并排序简介

代码展示

这段代码使用归并排序算法对输入的数组进行排序,并输出排序后的数组。在 merge_sort 函数中,通过递归调用将数组不断分割成更小的部分,然后将这些部分进行合并排序。在合并排序的过程中,通过比较左半部分和右半部分的元素大小,将较小的元素放入临时数组。最后,将临时数组中的元素复制回原数组,完成排序。最后在 main 函数中,输入数组并调用 merge_sort 函数进行排序,然后输出排序后的数组。

#include<iostream>
using namespace std;
const int N =1e5 + 7;
int n,q[N],tmp[N];

void merge_sort(int l,int r){
    if(l>=r) return ;
    int mid=l+r>>1;
    merge_sort(l,mid); // 递归调用左半部分
    merge_sort(mid+1,r); // 递归调用右半部分
    int i=l,j=mid+1;
    int k=1;
    while(i<=mid && j<=r){
        if(q[i]<=q[j]) tmp[k++]=q[i++]; // 左半部分的元素小于等于右半部分的元素,将左半部分的元素放入临时数组
        else {
            tmp[k++]=q[j++]; // 右半部分的元素小于左半部分的元素,将右半部分的元素放入临时数组
        }
    }
    while(i<=mid) tmp[k++]=q[i++]; // 处理剩余的左半部分的元素
    while(j<=r) tmp[k++]=q[j++]; // 处理剩余的右半部分的元素
    for(int i=l,j=1;i<=r;i++,j++)
    {
        q[i]=tmp[j]; // 将临时数组中的元素复制回原数组
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>q[i];
    merge_sort(1,n); // 调用归并排序函数
    
    // 输出排序后的数组
    for(int i=1;i<=n;i++) cout<<q[i]<<" ";
    cout<<endl;
    
    return 0;
}

逆序对和归并过程之间的联系

这里我们用图更能说明问题
在这里插入图片描述
观察上述这幅图,我们将数组一分为 2 ,并且左边的数组 和 右边的数组都是排好序的【正序】
那么我们再看
在这里插入图片描述
可能到这里会有小伙伴怀疑这样做会导致答案的重复,那么我们就再用一张图解释归并的本质
在这里插入图片描述
刚才我们举例的区间可成看出相邻的 区间 1 号,区间 2 号。

代码展示

#include<iostream>
using namespace std;
const int N =1e5 + 7;
int n,q[N],tmp[N];
long long res;
void merge_sort(int l,int r){
    if(l>=r) return ;
    int mid=l+r>>1;
    merge_sort(l,mid);
    merge_sort(mid+1,r);
    int i=l,j=mid+1;
    int k=1;
    while(i<=mid && j<=r){
        if(q[i]<=q[j]) tmp[k++]=q[i++];
        else {
            res+=mid-i+1;
            tmp[k++]=q[j++];
        }
    }
    while(i<=mid) tmp[k++]=q[i++];
    while(j<=r) tmp[k++]=q[j++];
    for(int i=l,j=1;i<=r;i++,j++)
    {
        q[i]=tmp[j];
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>q[i];
    merge_sort(1,n);
    cout<<res<<endl;
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

逆序对的数量(归并排序的深度理解) 的相关文章

  • GCC C++ (ARM) 和指向结构体字段的 const 指针

    假设有一个简单的测试代码 typedef struct int first int second int third type t define ADDRESS 0x12345678 define REGISTER type t ADDRE
  • 将处理后的图形绘制到另一个图形中

    我想将一个经过处理的图形绘制到另一个图形中 I have two graphics var gHead Graphics FromImage h var gBackground Graphics FromImage b Transform
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 在 C++ 中分割大文件

    我正在尝试编写一个程序 该程序接受一个大文件 任何类型 并将其分成许多较小的 块 我想我已经有了基本的想法 但由于某种原因我无法创建超过 12 kb 的块大小 我知道谷歌等上有一些解决方案 但我更感兴趣的是了解这个限制的根源是什么 然后实际
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • Guid 应包含 32 位数字和 4 个破折号

    我有一个包含 createuserwizard 控件的网站 创建帐户后 验证电子邮件及其验证 URL 将发送到用户的电子邮件地址 但是 当我进行测试运行时 单击电子邮件中的 URL 时 会出现以下错误 Guid should contain
  • ZLIB 解压缩

    我编写了一个小型应用程序 该应用程序应该解压缩以 gzip deflate 格式编码的数据 为了实现这一点 我使用 ZLIB 库 使用解压缩功能 问题是这个功能不起作用 换句话说 数据不是未压缩的 我在这里发布代码 int decompre
  • 如何在 VS 中键入时显示方法的完整文档?

    标题非常具有描述性 是否有任何扩展可以让我看到我正在输入的方法的完整文档 我想查看文档 因为我可以在对象浏览器中看到它 其中包含参数的描述和所有内容 而不仅仅是一些 摘要 当然可以选择查看所有覆盖 它可能是智能感知的一部分 或者我不知道它并
  • 在 C# 中将位从 ulong 复制到 long

    所以看来 NET 性能计数器类型 http msdn microsoft com en us library system diagnostics performancecounter aspx有一个恼人的问题 它暴露了long对于计数器
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • gdb 在 docker 上立即退出“进程已完成,退出代码 1”或 lldb“数据包返回错误 8”。另外:如何在 docker 中允许进行 C++ 调试

    这花了我一整天的时间才找到 所以我将其发布以供将来参考 我正在 docker 镜像上开发 C 我正在使用克利翁 我的代码是在调试模式下编译的 并且在运行模式下运行良好 但是当尝试调试时 进程会立即退出 并显示非常丰富的信息 Process
  • 单元测试失败,异常代码为 c0000005

    我正在尝试使用本机单元测试项目在 Visual Studios 2012 中创建单元测试 这是我的测试 TEST METHOD CalculationsRoundTests int result Calculations Round 1 0
  • std::bind 重载解析

    下面的代码工作正常 include
  • 我应该在应用程序退出之前运行 Dispose 吗?

    我应该在应用程序退出之前运行 Dispose 吗 例如 我创建了许多对象 其中一些对象具有事件订阅 var myObject new MyClass myObject OnEvent OnEventHandle 例如 在我的工作中 我应该使
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • 在基类集合上调用派生方法

    我有一个名为 A 的抽象类 以及实现 A 的其他类 B C D E 我的派生类持有不同类型的值 我还有一个 A 对象的列表 abstract class A class B class A public int val get privat
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS
  • 如何创建向后兼容 Windows 7 的缩放和尺寸更改每显示器 DPI 感知应用程序?

    我是 WPF 和 DPI 感知 API 的新手 正在编写一个在 Windows 7 8 1 和 10 中运行的应用程序 我使用具有不同每个显示器 DPI 设置的多个显示器 并且有兴趣将我的应用程序制作为跨桌面配置尽可能兼容 我已经知道可以将

随机推荐

  • C语言编程必将成为通用技能

    正文 为什么我们要学习编程 编程是当今时代不可或缺的核心技能 它不仅仅是程序员的专属领域 而是逐渐成为一种通用技能 被越来越多的人所需 想象一下 不久的将来 编程将变成人人都会的事情 而职业编程人员会逐渐减少 就像识字一样 编程将成为人们必
  • 用Java实现分页

    查询完全表之后 接下来要做的是查询总条数 和当前是第几页 总共有几页 包括数据 通过Java思想将封装为类 然后调用 pageBean java类可以当做通用的分页的类 Service作用是封装一类服务 比如说注册或者说登录 它是一类服务
  • IMS中Binder案例

    IMS中Binder案例 1 FWK层中AIDL形式 1 1 服务端实现Stub 1 2 客户端获取proxy 2 Native层中AIDL形式 2 1 服务端对应Bn端 2 2 客户端对应Bp端 android12 release 1 F
  • C++指针的使用

    一 指针的定义和使用 可以通过指针来保存一个变量的地址 例如 int a 2 就相当于内存中分出了一个内存块给变量a 而这个内存块中储存的数值为2 假设这个内存块的地址为0x2e 则可以通过定义一个指针来储存这个地址0x2e 指针就是一个地
  • Qt GraphicsView图形视图框架(Graphics View Framework)

    Graphics View提供了一个surface 用于管理大量定制的2D图形项并与之交互 还提供了一个View小部件 用于可视化项目 并支持缩放和旋转 该框架包含一个事件传播框架 该架构允许对场景中的项目提供精确的双精度交互功能 项目可以
  • IP地址总结

    IP地址分类 IP地址的编码分为两部分 网络号和主机号 A类地址默认子网掩码 255 0 0 0 B类地址默认子网掩码 255 255 0 0 C类地址默认子网掩码 255 255 255 0 D类默认子网掩码 255 255 255 25
  • 数学实验-迭代(Mathematica实现)

    一 实验名称 迭代 二 实验环境 Mathematica 10 3软件 三 实验目的 本实验通过Mathematica 10 3软件利用迭代求解方程的近似解 了解迭代方法在解决问题的收敛速度的异同 认识到函数的迭代是数学研究中的一个非常重要
  • P2P和CS架构

    P2P架构 Peer to Peer 特点 1 没有服务器 2 任意端系统直接通信 3 节点阶段性接入internet 4 节点可能更换ip地址 优缺点 优点 动态和随机性 缺点 难以管理 P2P和CS进行文件分发的比较 当文件数增多时 P
  • CSAPP阅读笔记——第二章:信息的表示和处理

    核心内容 编码原则 无符号 补码 浮点 溢出 无符号 补码 精度 浮点 一 信息存储 字节 存储最小单元 程序的内存管理是在虚拟地址层面上 字长 用于指明整数和指针数据的大小 编码虚拟地址 决定虚拟地址空间大小 数据大小 编码数字的格式 其
  • 【LLMs】关于LLMs的语义搜索

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • ElementUI组件el-time-picker的使用(只显示小时,分钟)

    在开发项目的时候 会经常用到时间选择器 但是ElementUI文档上给的示例是带有秒的 下面就是实现只显示小时和分钟的代码
  • libQt5XcbQpa.so.5多个导致load冲突

    直接运行labelme报错如下 qt qpa plugin Could not load the Qt platform plugin xcb in even though it was found This application fai
  • Windows中缺少mfc140.dll文件解决方法

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 如果是新手第一时间会认为是软件或游戏出错了 其实并不是这样 其主要原因就是你电脑系统的该dll文件丢失了或者损坏了 这时你只需下载这个mfc140 dll文件进行安装 前提是找到适合
  • 微信小程序蓝牙通信

    微信小程序目前只支持低功耗蓝牙 BLE 不支持经典蓝牙 微信小程序的当前最新版本为2 3 0 根据实际测试 对IOS支持很好 但对Android支持非常不好 各厂商的Android手机遇到的问题也不一样 因此要开发蓝牙功能 推荐只提供IOS
  • 极低级错误引发的“multiple definition of `XXX''”

    在文件x c中声明定义了一个变量temp 在y c中包含了x h头文件 编译时遇到 multiple definition of XXX 提示在y c文件中重定义了temp 反复检查代码 确定一切操作都无误 y c文件中也确定没有定义tem
  • python中init是什么_详细解读Python中的__init__()方法

    init 方法是重要的有两个原因 第一个原因是 初始化是最重要的步骤在一个对象的生命周期 每个对象都必须正确地初始化 才能正常工作 第二个原因是 init 参数值可以有多种形式 因为有很多方法可以提供参数值 init 有很多用例创建对象 我
  • html5 canvas 如何清空之前的绘制并重新绘制

    如果要重新绘制Canvas clearRect 不好用 将canvas的长宽重新设置成当前长宽即可 转载于 https blog 51cto com niyabuxing 1173359
  • vant组件库中list列表的使用(PullRefresh、van-list、van-empty结合使用)

  • python selenium playwright库使用教程 破解网页防止开发者模式 截取数据请求

    安装chromedriver 下载 chromedriver的版本一定要与Chrome的版本一致 不然就不起作用 有两个下载地址 1 http chromedriver storage googleapis com index html 2
  • 逆序对的数量(归并排序的深度理解)

    逆序对的数量问题 文章目录 逆序对的数量问题 问题详情 问题分析 归并排序简介 代码展示 逆序对和归并过程之间的联系 代码展示 问题详情 给定一个长度为 n 的整数数列 请你计算数列中的逆序对的数量 逆序对的定义如下 对于数列的第 i 个和