算法笔记_065:分治法求逆序对(Java)

目录

1 问题描述

2 解决方案

2.1 蛮力法

2.2 分治法(归并排序)

 


1 问题描述

给定一个随机数数组,求取这个数组中的逆序对总个数。要求时间效率尽可能高。

 

那么,何为逆序对?

引用自百度百科:

设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。
如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。

 例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。

 

 


2 解决方案

2.1 蛮力法

初步一看,使用蛮力是最直接也最简单的方法,但是时间效率为O(n^2)

即从第1个元素,开始依次和后面每一个元素进行大小比较,若大于,则逆序对个数加1

具体代码如下:

package com.liuzhen.systemExe;public class Main{//蛮力法求取数组A中逆序对数public int bruteReverseCount(int[] A) {int result = 0;for(int i = 0;i < A.length;i++) {for(int j = i;j < A.length;j++) {if(A[i] > A[j])result++;}}return result;}//获取一个随机数数组public int[] getRandomArray(int n) {int[] result = new int[n];for(int i = 0;i < n;i++) {result[i] = (int)( Math.random() * 50);  //生成0~50之间的随机数
        }return result;}public static void main(String[] args){long t1 = System.currentTimeMillis();Main test = new Main();int[] A = test.getRandomArray(50000);int result = test.bruteReverseCount(A);long t2 = System.currentTimeMillis();System.out.println("使用蛮力法得到结果:"+result+", 耗时:"+(t2 - t1)+"毫秒");}
}

运行结果(运行3次):

使用蛮力法得到结果:612226389, 耗时:8094毫秒使用蛮力法得到结果:610311942, 耗时:8015毫秒使用蛮力法得到结果:610657465, 耗时:8079毫秒

 

2.2 分治法(归并排序) 

除了蛮力法,此处可以借用归并排序的思想来解决此题,此时时间复杂度为O(n*logn)。归并排序,具体是先进行对半划分,直到最后左半边数组只有一个元素,右半边数组中也只有一个元素时,此时开始进行回溯合并。那么,计算逆序对个数的关键,就在于此处的回溯合并过程,当左半边元素(PS:回溯过程中,左半边和右半边元素均已是升序排序)中出现大于右半边元素时,那么左半边这个元素及其后面的所有元素均大于这个右半边元素,记这些元素个数为len,那么逆序对个数要自增len

具体代码如下:

package com.liuzhen.systemExe;public class Main{public long count = 0;   //全局变量,使用合并排序,计算逆序对数//使用归并排序方法计算数组A中的逆序对数public void getReverseCount(int[] A) {if(A.length > 1) {int[] leftA = getHalfArray(A, 0);   //数组A的左半边元素int[] rightA = getHalfArray(A, 1);  //数组A的右半边元素
            getReverseCount(leftA);getReverseCount(rightA);mergeArray(A, leftA, rightA);}}//根据judge值判断,获取数组A的左半边元素或者右半边元素public int[] getHalfArray(int[] A, int judge) {int[] result;if(judge == 0) {   //返回数组A的左半边result = new int[A.length / 2];for(int i = 0;i < A.length / 2;i++)result[i] = A[i];} else {    //返回数组的右半边result= new int[A.length - A.length / 2];for(int i = 0;i < A.length - A.length / 2;i++)result[i] = A[A.length / 2 + i];}return result;}//合并数组A的左半边和右半边元素,并按照非降序序列排列public void mergeArray(int[] A, int[] leftA, int[] rightA) {int len = 0;int i = 0;int j = 0;int lenL = leftA.length;int lenR = rightA.length;while(i < lenL && j < lenR) {if(leftA[i] > rightA[j]) {A[len++] = rightA[j++]; //将rightA[j]放在leftA[i]元素之前,那么leftA[i]之后lenL - i个元素均大于rightA[j]count += (lenL - i);   //合并之前,leftA中元素是非降序排列,rightA中元素也是非降序排列。所以,此时就新增lenL - i个逆序对} else {A[len++] = leftA[i++];}}while(i < lenL)A[len++] = leftA[i++];while(j < lenR)A[len++] = rightA[j++];}//获取一个随机数数组public int[] getRandomArray(int n) {int[] result = new int[n];for(int i = 0;i < n;i++) {result[i] = (int)( Math.random() * 50);  //生成0~50之间的随机数
        }return result;}public static void main(String[] args){long t1 = System.currentTimeMillis();Main test = new Main();int[] A = test.getRandomArray(50000);test.getReverseCount(A);long t2 = System.currentTimeMillis();System.out.println("分治法得到结果:"+test.count+", 耗时:"+(t2 - t1)+"毫秒");}
}

运行结果(运行3次):

分治法得到结果:612226489, 耗时:36毫秒分治法得到结果:610481152, 耗时:35毫秒分治法得到结果:612161208, 耗时:32毫秒

 

 

 

参考资料:

      1. 归并排序求逆序对

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

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

相关文章

c#copyto_String.CopyTo()方法以及C#中的示例

c#copytoC&#xff03;String.CopyTo()方法 (C# String.CopyTo() Method) String.CopyTo() method is used to copy a specified number of characters from given indexes of the string to the specified position in a character array. String.CopyTo()方法用于将指定数量的…

怎么查看我的php版本,怎样查看php版本

怎样查看php版本方法一&#xff1a;命令行查询如果已经配置好环境变量&#xff0c;直接在命令行中输入php -v&#xff0c;将会显示php的版本信息。如果没有配置环境变量&#xff0c;直接在命令行中进入到php的安装目录后&#xff0c;再输入命令php -v&#xff0c;如图所示是我在…

c ++ 继承_C ++继承| 查找输出程序| 套装1

c 继承Program 1: 程序1&#xff1a; #include <iostream>#include <string.h>using namespace std;class Person {char name[15];int age;public:void SetPerson(int age, char* name){this->age age;strcpy(this->name, name);}};class Student : publi…

xor在PHP是什么意思,?=‘在PHP中是什么意思?

万千封印因为它不会增加任何价值echo&#xff0c;我认为您希望了解PHP中的确切含义&#xff1a;Array([0] > Array([0] > 368 // T_OPEN_TAG_WITH_ECHO[1] > [2] > 1)[1] > Array([0] > 309 // T_VARIABLE[1] > $a [2] > 1)[2] > ; // U…

php curl keepalive,HTTPKeepAlive,开启还是关闭

所谓「HTTP Keep-Alive」&#xff0c;在维基百科里称为「HTTP Persistent Connection」&#xff0c;说白了就是复用HTTP连接&#xff0c;如此一来理论上客户端的用户体验会更流畅&#xff0c;但是与之相对服务端不得不维持大量的连接。开启还是关闭&#xff0c;这是个问题。一个…

如何使用ES6中的参数

ECMAScript 6&#xff08;或者叫 ECMAScript 2015&#xff09;是 ECMAScript 的最新标准&#xff0c;极大的提高了 JavaScript 中处理参数的能力。现在我们可以使用 rest 参数&#xff08;rest parameters&#xff09;、默认值&#xff08;default values&#xff09;和解构&am…

c++中tle是什么意思_如何在竞争性编程中克服TLE?

c中tle是什么意思什么是TLE&#xff1f; (What is TLE?) TLE means "Time Limit Exceed". So, in competitive programming, there are some constraints with a specific time limit (normally for each input 1 sec) and your task is to write your code in such…

美颜相机window 开源_X-Window系统| 免费和开源软件

美颜相机window 开源X窗口系统 (The X-Window System) The X-Window System is a GUI that sits over Linux. Not at all like Microsoft Windows, the X Window System can glance and work in an enormously wide range of ways. It can work smoothly or lag, look excellen…

php 代码 自动检查工具下载,PHP_CodeSniffer安装和使用教程(自动代码检查规范工具)...

在我们开发中都会讲究代码规范&#xff0c;若是个人开发者&#xff0c;代码规范与否&#xff0c;只要自己看得懂便可以了&#xff0c;但是在团队协作中&#xff0c;代码规定尤为重要&#xff0c;下面&#xff0c;我们介绍一款PHP_CodeSniffer&#xff0c;自动检查代码规范的工具…

国际象棋之跳马程序

问题描述: 假设国际象棋棋盘有5*5共25个格子。设计一个程序,使棋子从初始位置&#xff08;棋盘格编号为1的位置)开始跳马,能够把棋盘的格子全部走一遍,每个格子只允许走一次。要求: 1) 输出一个解(用二维数组来记录马跳的过程,即[步号,棋盘格编号],左上角为第一步起点)&#xf…

kafka安装使用

版本&#xff1a;kafka_2.11-0.10.1.0 (之前安装2.10-0.10.0.0&#xff0c;一直出问题) 安装Springboot结合Kafka的使用安装 下载并解压代码 wget http://mirrors.cnnic.cn/apache/kafka/0.10.0.0/kafka_2.10-0.10.0.0.tgz #http://kafka.apache.org/downloadstar -zxvf kafka…

php获取上传文件路径 fakepath,JavaScript_js获取上传文件的绝对路径实现方法,在html中input type=file - phpStudy...

js获取上传文件的绝对路径实现方法在html中function upload() {var filename document.getElementById("importFile").value;// 这时的filename不是 importFile 框中的值alert(filename);}如上面的代码&#xff0c;用文件上传对话框选择文件后&#xff0c;如果选择&…

在Bootstrap中使用类的按钮类型

Bootstrap has 7 different types of buttons with contextual classes from which we can create buttons easily by using these classes (.btn-default, .btn-success, .btn-danger, .btn-primary, .btn-info, .btn-warning, .btn-link). Bootstrap具有上下文类型的 7种不同…

php json encode中文乱码,php json_encode中文乱码如何解决

php encode中文乱码的解决办法&#xff1a;首先打开相应的PHP文件&#xff1b;然后使用正则语句“preg_replace("#\\\u([0-9a-f]{4})#ie","iconv(UCS-2BE, UTF-8...)”将编码替换成中文即可。本文列举3个方法&#xff0c;实现json_encode()后的string显示中文问…

乡村图景(转载)

转自: http://cul.qq.com/a/20160205/046437.htm 我丈夫家在湖北孝感孝昌县的一个村子。2005年第一次过年回到他家&#xff0c;印象最深的就是嫂子。我暗自问当时的男友&#xff0c;“哥哥尽管算不上特别帅气&#xff0c;但为何找了这么难看的嫂子&#xff1f;”后来才发现&…

stl向量最大值_C ++ STL中向量的最小和最大元素

stl向量最大值Given a vector and we have to find the smallest (minimum) and largest (maximum) elements. 给定一个向量&#xff0c;我们必须找到最小(最小)和最大(最大)元素。 查找向量的最小和最大元素 (Finding vectors minimum & maximum elements) To find minim…

oracle如何设置备份计划任务,Oracle数据库设置任务计划备份一周的备份记录

Oracle 数据库备份&#xff1a;--保留最近一周的备份记录&#xff1b;正文&#xff1a;开始代码如下:echo 设置备份文件存放文件夹...set "tbufE:\Cway\backup"echo 设置备份文件名(以星期几命名&#xff0c;即备份文件只保存最近一周)...set name%date%set name%nam…

索引(转载自百度百科)

Oracle索引 编辑本词条缺少信息栏、名片图&#xff0c;补充相关内容使词条更完整&#xff0c;还能快速升级&#xff0c;赶紧来编辑吧&#xff01;在oracle索引是一种供服务器在表中快速查找一个行的数据库结构。合理使用索引能够大大提高数据库的运行效率。目录 1 概念及作用 2…

阿姆斯特朗数_阿姆斯特朗的功能依赖公理 数据库管理系统

阿姆斯特朗数Armstrong axioms are a complete set of inference rules or axioms, introduced and developed by William W. Armstrong in 1974. The inference rules are sound which is used to test logical inferences of functional dependencies. The axiom which also …

ORACLE JOB 失败 查看,Oracle JOB异常中断原因分析

注释今天研发同事找我确认 PKG_WMS.proc_TaskMain 存储的 job 是否还在运行&#xff0c;竟发现 dba_jobs.NEXT_DATE4000/1/1&#xff0c;如下看看究竟原因吧~JOB 信息&#xff1a;参数&#xff1a;BROKEN : 中断标记 ,N 启动、Y 中断 --> DBMS_JOBS.BROKEN(job_id,TRUE/FA…