vb.net中递归退到最外层_数组中的逆序对

513bdfc4c068a2681753f5825a18465f.png

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

输入描述:

题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4 
对于%75的数据,size<=10^5 
对于%100的数据,size<=2*10^5

示例:

输入:
{1, 2, 3, 4, 5, 6, 7, 0}
返回值:
7

解题思路及代码

方法一:暴力列举

暴力列举所有的数对,然后判断是否逆序。

具体方法是:按住一个arr[i], 依次判断{i+1 ... n-1]是否满足条件。n为数组的大小。

代码如下:

class Solution {
private:const int kmod = 1000000007;
public:int InversePairs(vector<int> data) {int ret = 0;int n = data.size();for (int i = 0; i < n; ++i) {for (int j = i + 1; j < n; ++j) {if (data[i] > data[j]) {ret += 1;ret %= kmod;}}}return ret;}
};

对于10^5数据,O(N^2)算法显然超时。

时间复杂度:O(N^2)

空间复杂度:O(1)

方法二:归并排序思想

对数组一边进行归并排序,一边计算逆序对。

首先明确归并排序的过程:

  • 递归划分整个区间为基本相等的左右两个区间
  • 合并两个有序区间

归并排序的代码:

// 合并过程
void merge__(vector<int> &arr, int l, int mid, int r) {// 在这个地方创建额外空间,是一种不好的做法,更好的做法是:直接在最外层开辟一个足够大的数组,然后传引用到函数。vector<int> tmp(r - l + 1);int i = l, j = mid + 1, k = 0;while (i <= mid && j <= r) {if (arr[i] >= arr[j]) {tmp[k++] = arr[j++];}else {tmp[k++] = arr[i++];}}while (i <= mid) {tmp[k++] = arr[i++];}while (j <= r) {tmp[k++] = arr[j++];}for (k = 0, i = l; i <= r; ++i, ++k) {arr[i] = tmp[k];}
}// 递归划分过程
void merge_sort__(vector<int> &arr, int l, int r) {// 只有一个数字,则停止划分if (l >= r) {return;}int mid = l + ((r - l) >> 1);merge_sort__(arr, l, mid);merge_sort__(arr, mid + 1, r);// 合并两个有序区间merge__(arr, l, mid, r);
}
// 要排序的数组 arr
void merge_sort(vector<int>& arr) {merge_sort__(arr, 0, arr.size() - 1);
}

本题中如何利用归并排序的思想?

如果两个区间为[4, 3] 和[1, 2]

那么逆序数为(4,1),(4,2),(3,1),(3,2),同样的如果区间变为有序,比如[3,4] 和 [1,2]的结果是一样的,也就是说区间有序和无序结果是一样的。

但是如果区间有序会有什么好处吗?

当然,如果区间有序,比如[3,4] 和 [1,2]

如果3 > 1, 显然3后面的所有数都是大于1, 这里为 4 > 1, 明白其中的奥秘了吧。所以我们可以在合并的时候利用这个规则。

代码如下:

class Solution {
private:const int kmod = 1000000007;
public:int InversePairs(vector<int> data) {int ret = 0;// 在最外层开辟数组vector<int> tmp(data.size());merge_sort__(data, tmp, 0, data.size() - 1, ret);return ret;}void merge_sort__(vector<int> &arr, vector<int> &tmp, int l, int r, int &ret) {if (l >= r) {return;}int mid = l + ((r - l) >> 1);merge_sort__(arr, tmp, l, mid, ret);merge_sort__(arr, tmp, mid + 1, r, ret);merge__(arr, tmp, l, mid, r, ret);}void merge__(vector<int> &arr, vector<int> &tmp, int l, int mid, int r, int &ret) {int i = l, j = mid + 1, k = 0;while (i <= mid && j <= r) {if (arr[i] > arr[j]) {tmp[k++] = arr[j++];// 奥妙之处ret += (mid - i + 1);ret %= kmod;}else {tmp[k++] = arr[i++];}}while (i <= mid) {tmp[k++] = arr[i++];}while (j <= r) {tmp[k++] = arr[j++];}for (k = 0, i = l; i <= r; ++i, ++k) {arr[i] = tmp[k];}}};

Java 版:

private long cnt = 0;
private int[] tmp;  // 在这里声明辅助数组,而不是在 merge() 递归函数中声明public int InversePairs(int[] nums) {tmp = new int[nums.length];mergeSort(nums, 0, nums.length - 1);return (int) (cnt % 1000000007);
}private void mergeSort(int[] nums, int l, int h) {if (h - l < 1)return;int m = l + (h - l) / 2;mergeSort(nums, l, m);mergeSort(nums, m + 1, h);merge(nums, l, m, h);
}private void merge(int[] nums, int l, int m, int h) {int i = l, j = m + 1, k = l;while (i <= m || j <= h) {if (i > m)tmp[k] = nums[j++];else if (j > h)tmp[k] = nums[i++];else if (nums[i] <= nums[j])tmp[k] = nums[i++];else {tmp[k] = nums[j++];this.cnt += m - i + 1;  // nums[i] > nums[j],说明 nums[i...mid] 都大于 nums[j]}k++;}for (k = l; k <= h; k++)nums[k] = tmp[k];
}

时间复杂度:O(NlogN)

空间复杂度:O(N)

解析参考来自:

数组中的逆序对_牛客网​www.nowcoder.com

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

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

相关文章

java实现条形图,JavaFX条形图

本文概述通常, 条形图可以定义为使用矩形条形表示数据的图。条的长度表示绘制在其中一根轴上的精确数值数据值。矩形条可以在图表上水平或垂直绘制。在下图中, 条形图显示了工程各个分支中的学生人数。 X轴是类别轴, 显示了不同的分支, 而Y轴是数字轴, 显示了特定分支中的学生人…

php excel 垂直居中,完美实现文字图片水平垂直居中

垂直居中是一个历史悠久的大问题&#xff0c;要做到兼容所有浏览器少不了要花点时间&#xff0c;网上也流传了很多解决方案&#xff0c;但没发现比我现在用的方案更完美&#xff0c;至少在我的项目是如此。项目中要用到垂直居中而碰到兼容性问题的&#xff0c;一般都是以下几种…

cd短是什么意思_每日命令|pwd、cd

01 命令简介上回说到《每日命令 | ls》&#xff0c;今天我们来说一说pwd命令和cd命令。pwd命令——返回当前工作目录名称。cd命令——改变工作目录。什么是工作目录&#xff1f;举个例子&#xff1a;我在北京上班&#xff0c;那我的工作地点就是北京&#xff1b;后来我到上海上…

sql 查询表结构_SQL查询语句的完整结构解析

SELECT语句完整的句法模板&#xff1a;SELECT [DISTINCT] FROM [ JOIN ON ][WHERE ][GROUP BY [HAVING ]][ORDER BY &#xff0c;...]上述句法模版中的[ ]表示该部分可选。SELECT整个语句的执行过程为&#xff1a;(1) 读取FORM子句中表、视图的数据。(2) 存在连接表时&…

基于matlab实现的云模型计算隶属度,基于MATLAB实现的云模型计算隶属度

”云”或者’云滴‘是云模型的基本单元&#xff0c;所谓云是指在其论域上的一个分布&#xff0c;可以用联合概率的形式(x&#xff0c; u)来表示云模型用三个数据来表示其特征期望&#xff1a;云滴在论域空间分布的期望&#xff0c;一般用符号Εx表示。熵&#xff1a;不确定程度…

二陈丸配什么吃不上火_宝妈一个人带孩子是什么感觉?前三种场景,不知道是怎么熬过来的...

导语&#xff1a;很多人认为一个家庭主妇很轻松&#xff0c;每天就带带孩子&#xff0c;其他什么都不需要做&#xff0c;远远没有那些人说的那么辛苦&#xff0c;无论是老公还是很多婆婆都认为是在家享福呢&#xff0c;经常就会甩出一句话“每天不就带个孩子吗&#xff1f;至于…

php怎么分割页面,将一个页面分成多个html文件(静态html分割页面)

静态html分割页面&#xff0c;达到类似PHP等动态页面的include引入页面效果。用html把首页分成三个文件web.png在PHP、JSP等动态页面开发中&#xff0c;页面里引入其它页面只需include()进来就可以实现页面的分离。如果用HTML&#xff0c;也是可以实现页面的分割的。两种方法&a…

zbar扫描无法近距离扫码_生意好时最怕收银出故障,这几个扫码枪的常见问题你一定要知道...

文|杭州丰收收不怕生意不够好&#xff0c;就怕生意好时收银出故障。这几天丰收收经常接到询问&#xff0c;说自己商铺所在的位置信号非常不好&#xff0c;很多客户等了很久没法付款&#xff0c;索性就不买了。看着上门的生意就这么走了&#xff0c;心里很不是滋味。遭遇这种经历…

你觉得外观模式和代理模式的联系和区别是什么?_GoF23种设计模式

UML泛化&#xff08;继承非抽象类&#xff09;&#xff1a;带空心三角形的直线表示实现&#xff08;继承抽象类&#xff0c;类实现接口&#xff09;&#xff1a;带空心三角形的虚线表示依赖&#xff1a;类与类之间最弱的关系&#xff0c;依赖可以简单的理解一个类使用了另一个类…

反注入技术:防范非法 Call 调用的探讨

DLL 注入是一种常见的技术&#xff0c;用于向目标进程注入外部的动态链接库&#xff08;DLL&#xff09;&#xff0c;以执行某些特定的操作。这种技术在恶意软件、游戏作弊等场景中被广泛使用&#xff0c;因此&#xff0c;研究和实施一些反注入技术对于提高应用程序的安全性是至…

tp5 php跨域,TP5.1解决跨域

TP5.1解决跨域博客说明文章所涉及的资料来自互联网整理和个人总结&#xff0c;意在于个人学习和经验汇总&#xff0c;如有什么地方侵权&#xff0c;请联系本人删除&#xff0c;谢谢&#xff01;介绍在前后端分离开发的时候就会遇到跨域的问题&#xff0c;在本地调试的时候可能不…

如何避免_如何避免变频器受负载冲击

电工学习网&#xff1a;www.diangon.com关注电工学习网官方微信公众号“电工电气学习”&#xff0c;收获更多经验知识。为了保障变频器的安全运行&#xff0c;避免变频器受负载冲击&#xff0c;必须做好以下几点:㈠尽量保证变频器有充足的加减速时间变频器在开机或升速时&#…

哪种语言 连接 oracle,Go语言连接Oracle(就我这个最全)

综合参考了网上挺多的方案倒腾了半天终于连接好了Go都出来这么多年了还没有个Oracle的官方驱动。。。过程真的很蛋疼。。一度想放弃直接连ODBC首先交代一下运行环境和工具版本&#xff1a;WIN10MINGW64ORACLE INSTANCCLIENT_18_3 x64Jetbrins Goland看完这篇文章&#xff0c;…

补丁程序正在运行_针对微软4月14日更新补丁会导致蓝屏问题的检测及解决方法...

近期&#xff0c;我们接连收到用户求助&#xff0c;在使用电脑过程中会突然出现蓝屏问题&#xff0c;经火绒工程师分析发现&#xff0c;大部分用户出现蓝屏问题&#xff0c;是因为安装了微软于4月14日推送的补丁所致(详见下图)。目前微软方面表示正在调查相关问题。Win10系统蓝…

商城html源码_Java开源商城源码推荐,从菜鸡到大神,永远绕不开的商城系统

每个Java程序员&#xff0c;从懵逼菜鸡&#xff0c;再到懵懂菜鸟&#xff0c;再到小鸟&#xff0c;大鸟&#xff0c;最后到技术大神&#xff0c;始终绕不开商城系统&#xff0c;里面蕴含了大量的业务&#xff0c;涉及到了大量的知识点和解决方案。今天锋哥介绍一款Java开源商城…

cpu只能单通道是什么表现_【小白入门】为什么要组内存双通道?

更新时间&#xff1a;2020年5月11日 内容提要&#xff1a; 1.内存双通道的原理 2.如何组双通道很多小白在购买内存的时候&#xff0c;不知道该购买一根单16G还是两根单8G&#xff0c;看完本篇文章你将知道内存双通道的优势。1.内存双通道的原理选择两根单8G组成双通道&#xff…

雷云3灯光配置文件_雷蛇的哪种键盘最适合入手?3款最佳雷蛇键盘推荐。

更新时间2020.8.6本次主要内容是雷蛇的三款不同价位的雷蛇键盘推荐&#xff0c;有需要的小伙伴可以看一下哦&#xff0c;也许你想要入手的键盘就在其中。---------------------------------雷蛇黑寡妇蜘蛛精英版--------------------------------------黑寡妇蜘蛛精英版在猎魂光…

某些您可以编辑的区域交叠在一起 可能不能同时显示_DX200操作要领—修改与编辑程序(三十九)...

3.5 修改程序3.5.1 程序的调出1. 选择主菜单中的【程序内容】2. 选择【程序选择】–显示程序一览表。3. 选择要调出的程序3.5.2 程序相关画面程序相关画面有下面5种&#xff0c;可以确认/编辑每个程序的设定或登录。•程序标题画面显示和编辑注释、登录日期、编辑禁止的状态等。…

求二叉树中以x为根的子树的深度_还在玩耍的你,该总结啦!(本周小结之二叉树)...

给「代码随想录」一个星标吧&#xff01;❝有学习就要有总结❞本周小结本周赶上了十一国庆&#xff0c;估计大家已经对本周末没什么概念了&#xff0c;但是我们该做总结还是要做总结的。本周的主题其实是「简单但并不简单」&#xff0c;本周所选的题目大多是看一下就会的题目&a…

钉钉功能介绍_平棉集团组织召开阿里钉钉办公系统基础功能培训会

4月11日上午&#xff0c;平棉集团在总部26楼多媒体会议室组织召开阿里钉钉办公系统基础功能培训会&#xff0c;邀请河南一一信息技术公司经理杨杉前来授课。集团公司董事长张先顺及公司领导陈亚民、王仲山、王向阳、陶尚林&#xff0c;各生产经营单位主管销售工作的负责人和公司…