求数组中的逆序对的数量----剑指offer36题
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数:
如数组{7,5,6,4},逆序对总共有5对,{7,5},{7,6},{7,4},{5,4},{6,4};
思路1:暴力解法,顺序扫描整个数组,每扫描到一个数字的时候,逐个比较该数字和它后面的数字的大小。如果后面的数字比它小,则这两个数字就组成一个逆序对。假设数组中含有n个数字,由于每个数字都要和O(n)个数字作比较,因此这个算法的时间复杂度是O(n2)。
思路2:分治思想,采用归并排序的思路来处理,如下图,先分后治:
先把数组分解成两个长度为2的子数组,再把这两个子数组分解成两个长度为1的子数组。接下来一边合并相邻的子数组,一边统计逆序对的数目。在第一对长度为1的子数组{7}、{5}中7>5,因此(7,5)组成一个逆序对。同样在第二对长度为1的子数组{6},{4}中也有逆序对(6,4),由于已经统计了这两对子数组内部的逆序对,因此需要把这两对子数组进行排序,避免在之后的统计过程中重复统计。
逆序对的总数=左边数组中的逆序对的数量+右边数组中逆序对的数量+左右结合成新的顺序数组时中出现的逆序对的数量;
总结统计数组逆序对的过程:先把数组分隔成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。在统计逆序对的过程中,还需要对数组进行排序,其实这个排序过程就是归并排序的思路。
代码实现思路如下:
//数组中的逆序对
public static int InversePairs(int[] array){
if(array==null||array.length<=1)
return 0;
int[] copy = new int[array.length];
for(int i=0;i<array.length;i++){
copy[i] = array[i];
}
return mergeCount(array, copy, 0, array.length-1);
} public static int mergeCount(int[] array, int[] copy, int start, int end){
if(start==end){
copy[start] = array[start];
return 0;
}
int mid = (start+end)>>1;
int leftCount = mergeCount(copy, array, start, mid);
int rightCount = mergeCount(copy, array, mid+1, end); int i = mid;//i初始化为前半段最后一个数字的下标
int j = end;//j初始化为后半段最后一个数字的下标
int index = end;//辅助数组复制的数组的最后一个数字的下标
int count = 0;//计数--逆序对的数目
while(i>=start&&j>=mid+1){
if(array[i]>array[j]){
copy[index--] = array[i--];
count += j-mid;
}else{
copy[index--] = array[j--];
}
}
for(;i>=start;i--){
copy[index--] = array[i];
}
for(;j>=mid+1;j--){
copy[index--] = array[j];
}
return leftCount+rightCount+count;
}
求数组中的逆序对的数量----剑指offer36题的更多相关文章
- 剑指Offer 35. 数组中的逆序对 (数组)
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- 剑指Offer(三十五):数组中的逆序对
剑指Offer(三十五):数组中的逆序对 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/bai ...
- 归并排序(归并排序求逆序对数)--16--归并排序--Leetcode面试题51.数组中的逆序对
面试题51. 数组中的逆序对 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出 ...
- [剑指OFFER] 数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 分析:利用归并排序的思想,分成2部分,每一部分按照从大到 ...
- MergeSort归并排序和利用归并排序计算出数组中的逆序对
首先先上LeetCode今天的每日一题(面试题51. 数组中的逆序对): 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. ...
- (剑指Offer)面试题36:数组中的逆序对
题目: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 思路: 1.顺序扫描 顺序扫描整个数组,每扫描到一个数字,就将该数 ...
- 九度OJ 1348 数组中的逆序对 -- 归并排序
题目地址:http://ac.jobdu.com/problem.php?pid=1348 题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求 ...
- [jobdu]数组中的逆序对
http://ac.jobdu.com/problem.php?pid=1348 数组中的逆序对也是个常见的题目,算法导论中也有一些描述,参考:http://www.cnblogs.com/wuyue ...
- 【剑指offer】面试题36:数组中的逆序对
题目: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 思路: 归并排序的合并过程.主要是考虑合并两个有序序列时,计算逆序 ...
随机推荐
- jquery select radio
Query获取Select选择的Text和Value: 语法解释: 1. $("#select_id").change(function(){//code...}); //为S ...
- WPF Demo6
通知项熟悉.数据绑定 using System.ComponentModel; namespace Demo6 { /// <summary> /// 通知项属性 /// </sum ...
- shell打印彩色输出
字体颜色(8种,3开头) 重置=0,黑色=30,红色=31,绿色=32, 黄色=33,蓝色=34, 洋红=35, 青色=36, 白色=37. 背景颜色(8种,4开头) 重置=0,黑色=40,红色=41 ...
- Kubernetes集群安全配置案例
Kubernetes 系统提供了三种认证方式:CA 认证.Token 认证 和 Base 认证.安全功能是一把双刃剑,它保护系统不被攻击,但是也带来额外的性能损耗.集群内的各组件访问 API Serv ...
- [转]MSSQL 判断临时表是否存在
原文来自:http://www.cnblogs.com/szfhquan/p/4229150.html 方法一: 1 if exists (select * from tempdb.dbo.sysob ...
- Hessian与Webservice的区别
Hessian:hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能,相比WebService,Hessian更简单.快捷. 采用的是二进制RPC协议,因为 ...
- python protobuf序列化repeated运用
下面是proto描述文件的定义 message Person { required string name = 1; required int32 id = 2; optional string em ...
- 解决Mac nginx问题 [emerg] 54933#0: bind() to 0.0.0.0:80 failed (13: Permission denied)
brew services restart nginx Stopping nginx... (might take a while) ==> Successfully stopped nginx ...
- JS - 循环,条件if,switch,while
1.循环格式: 定义初始值 终止条件 // 1.将i的值写在里面 for(var i=0;i;i ++){ console.log(i); }// 2.也可以将i的值写在外面,分号必须还在 va ...
- uva-185-暴力枚举
请相信,这是一道水题,读了一周的题意 题意: 题目里面描述的那三个条件可以直接无视,关于罗马数字只要知道一个规则即可,映射如下 I 1 V 5X 10 L 50C 100 D 50 ...