剑指offer-36:数组中的逆序对
参考:1、 https://www.geeksforgeeks.org/merge-sort/
2、《剑指Offer:名企面试官精讲典型编程题》
题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
- 对于%50的数据,size<=10^4
- 对于%75的数据,size<=10^5
- 对于%100的数据,size<=2*10^5
示例1 输入:1,2,3,4,5,6,7,0 输出:7
解题思路1 (暴力法,时间复杂度: O(n^2))
这个方法最简单直接,顺序扫描整个数组,每扫到一个数,逐个比较其后面的所有数,如果构成逆序对,则计数+1。代码没啥难度,略了。
解题思路2 (分治法,时间复杂度: O(nlogn),空间复杂度:O(n))
public int InversePairs(int[] array) {
if (array.length < 2) {
return 0;
}
return divideAndConquer(array, 0, array.length);
}
public int divideAndConquer(int[] array, int l, int r) {
if (l >= r - 1) return 0;
int mid = (l + r) / 2;
int count = 0;
int countL = divideAndConquer(array, l, mid);
int countR = divideAndConquer(array, mid, r);
int[] left = Arrays.copyOfRange(array, l, mid);
int[] right = Arrays.copyOfRange(array, mid, r);
int i = left.length - 1;
int j = right.length - 1;
for (int k = r - 1; k >= l; k--) {
// two cases: left is empty or right is empty
if (i < 0) {
array[k] = right[j];
j--;
continue;
} else if (j < 0) {
array[k] = left[i];
i--;
continue;
}
if (left[i] > right[j]) {
count += j + 1;
if (count > 1000000007) {
count %= 1000000007;
}
array[k] = left[i];
i--;
} else {
array[k] = right[j];
j--;
}
}
return (count + countL + countR) % 1000000007;
}
这一题的解法是在归并排序(Merge Sort) 的基础上修改得到的。Merge Sort使用的是分治法的思想。分治法 (divide and conquer) 是将一个复杂的问题,分成两个或多个相同或者相似的子问题,再把子问题分成更小的子问题,一直分到子问题足够简单来求解,最后再把子问题的解合并成原问题的解。归并排序法的时间复杂度为 O(nlogn),空间复杂度为 临时的数组 + 递归时压入栈的数据占用的空间 = n + logn,即 O(n)。
以数组 {7, 5, 6, 4} 为例进行分析,解题过程如图5.2所示。首先将数组拆成至长度为1的子数组,然后一边合并一边统计逆序对的数目。在第一对长度为1 的子数组 {7}、{5}中,有一对逆序对 (7, 5)。在第二对长度为1的子数组 {6}、{4}中,也有一对逆序对(6, 4)。在统计完这两对逆序对后,需要分别对他们进行排序,如图 5.2(c),以免在以后的统计过程中再重复统计。

然后需要统计两个长度为2的子数组之间的逆序对,并合并两个子数组,如图5.3所示。两个子数组分别从末尾开始判断数的大小,如图5.2(a)中指针P1、P2。如果 P1 大于 P2,则构成逆序对,并且逆序对的数目等于第二个子数组中剩余数字的个数,即 P2 以及之前的所有数字的个数。如果 P1 小于或等于 P2, 则不构成逆序对。每次比较的时候,我们都把较大的数字从后往前复制到一个辅助数组,确保辅助数组中的数字是递增排序的。在把较大的数字复制到辅助数组之后,把对应的指针向前移动一位,接下来进行下一轮比较。

以此类推,使用这个方法去求出其他数组的逆序对个数。在解这一题的时候,还有一点需要注意,除了需要将总输出结果 (count + countL + countR) 对1000000007取模,还要在计算过程中将 count += j + 1 对1000000007取模,以免count超出 Integer.MAX_VALUE。
剑指offer-36:数组中的逆序对的更多相关文章
- 剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组
剑指 Offer 51. 数组中的逆序对 Offer_51 题目描述 方法一:暴力法(双层循环,超时) package com.walegarrett.offer; /** * @Author Wal ...
- 【Java】 剑指offer(51)数组中的逆序对
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成 ...
- 【剑指offer】数组中的逆序对
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/mmc_maodun/article/details/27520535 转载请注明出处:http:// ...
- Go语言实现:【剑指offer】数组中的逆序对
该题目来源于牛客网<剑指offer>专题. 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对10000 ...
- 【剑指offer】数组中的逆序对。C++实现
原创文章,转载请注明出处! 博客文章索引地址 博客文章中代码的github地址 # 题目 # 思路 基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目.统计逆序对 ...
- 微软面试题:剑指 Offer 51. 数组中的逆序对 Hard 出现次数:3
题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对. 输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出: 5 限制: ...
- 剑指Offer 35. 数组中的逆序对 (数组)
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- [剑指Offer] 35.数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- 剑指offer:数组中的逆序对
题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%100 ...
- 剑指offer——54数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
随机推荐
- element table 先显示暂无数据 之后再加载数据 问题
项目中的表格请求数据时,进去页面,先出现 ''暂无数据'' 字样闪现一下之后在进行加载数据,用户体验十分不好 解决办法: <template> <el-table :data=&qu ...
- 鲲鹏凌云,并行科技Paramon通过华为云鲲鹏云服务兼容性认证
随着Cloud2.0时代到来,5G技术开始应用普及,超算云服务需求不断升级,业务多样性.数据多样性不断延伸.2019年7月,华为召开鲲鹏计算产业发展峰会,依托在联接领域坚实的基础,华为未来将着力打造智 ...
- 一条数据的HBase之旅,简明HBase入门教程3:适用场景
[摘要] 这篇文章继HBase数据模型之后,介绍HBase的适用场景,以及与一些关键场景有关的周边技术生态,最后给出了本文的示例数据 华为云上的NoSQL数据库服务CloudTable,基于Apach ...
- luogu CF16E Fish
题目描述 有n条鱼,编号从1到n,住在湖里.每天有一对鱼相遇, 彼此相遇的概率是一样的.如果两条标号为i和j的鱼见面,第一只吃了第二只的概率为a{i,j},第二只会吃了第一只的概率为a{j,i}=1- ...
- Java修炼——插入排列,选择排列
话不多说,直接上代码: package com.bjsxt.Array; import java.util.Arrays; public class TestSort { //选择排序 //插入排列 ...
- 胸部CT提取分割肺部
1. 肺部分割提取简介 在处理胸部CT时,我们常常需要获取肺部的一个mask,也就是将肺部结构从数据中提取出来.二维图像还好说,但是三维图像就会变得复杂复杂一点.肺部的分割常常做后续操作的预处理,所以 ...
- POJ3111
Demy has n jewels. Each of her jewels has some value vi and weight wi. Since her husband John got br ...
- 小程序 - 解决IOS端使用css滤镜渲染出现异常
在页面渲染时,GPU默认不会开启.当css样式中出现某些规则时,就会开启GPU加速,让动画运行的更加流畅,最显著的象征就是元素的3D变换. 这些就是我们通常所说的css硬件加速,但我们有时候并不需要用 ...
- gtest、cmake使用
gtest github: https://github.com/google/googletest 学习:玩转Google开源C++单元测试框架Google Test系列(gtest)(总) 一.安 ...
- 【HTTP】HTTP 的15个常见知识点复习
前言 自从入职新公司到现在,我们前端团队内部一直在做 ?每周一练 的知识复习计划,我之前整理了一个 每周一练 之 数据结构与算法 学习内容,大家也快去看看~~ 最近三周,主要复习 网络基础 相关的知识 ...