题目描述

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

解题思路

剑指offer的解法
看到这个题目,我们的第一反应是顺序扫描整个数组。每扫描到一个数组的时候,逐个比较该数字和它后面的数字的大小。如果后面的数字比它小,则这两个数字就组成了一个逆序对。假设数组中含有n个数字。由于每个数字都要和O(n)这个数字比较,因此这个算法的时间复杂度为O(n^2)。
我们以数组{7,5,6,4}为例来分析统计逆序对的过程。每次扫描到一个数字的时候,我们不拿ta和后面的每一个数字作比较,否则时间复杂度就是O(n^2),因此我们可以考虑先比较两个相邻的数字。

(a) 把长度为4的数组分解成两个长度为2的子数组;
(b) 把长度为2的数组分解成两个成都为1的子数组;
© 把长度为1的子数组 合并、排序并统计逆序对 ;
(d) 把长度为2的子数组合并、排序,并统计逆序对;
在上图(a)和(b)中,我们先把数组分解成两个长度为2的子数组,再把这两个子数组分别拆成两个长度为1的子数组。接下来一边合并相邻的子数组,一边统计逆序对的数目。在第一对长度为1的子数组{7}、{5}中7大于5,因此(7,5)组成一个逆序对。同样在第二对长度为1的子数组{6}、{4}中也有逆序对(6,4)。由于我们已经统计了这两对子数组内部的逆序对,因此需要把这两对子数组 排序 如上图(c)所示, 以免在以后的统计过程中再重复统计。

接下来我们统计两个长度为2的子数组子数组之间的逆序对。合并子数组并统计逆序对的过程如下图如下图所示。

我们先用两个指针分别指向两个子数组的末尾,并每次比较两个指针指向的数字。如果第一个子数组中的数字大于第二个数组中的数字,则构成逆序对,并且逆序对的数目等于第二个子数组中剩余数字的个数,如下图(a)和(c)所示。如果第一个数组的数字小于或等于第二个数组中的数字,则不构成逆序对,如图b所示。每一次比较的时候,我们都把较大的数字从后面往前复制到一个辅助数组中,确保 辅助数组(记为copy) 中的数字是递增排序的。在把较大的数字复制到辅助数组之后,把对应的指针向前移动一位,接下来进行下一轮比较。

过程:先把数组分割成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。在统计逆序对的过程中,还需要对数组进行排序。如果对排序算法很熟悉,我们不难发现这个过程实际上就是归并排序。

代码实现

class Solution {public:int InversePairs(vector<int> data) {int length=data.size();if(length<=0)return 0;//vector<int> copy=new vector<int>[length];vector<int> copy;for(int i=0;i<length;i++)copy.push_back(data[i]);long long count=InversePairsCore(data,copy,0,length-1);//delete[]copy;return count%1000000007;}long long InversePairsCore(vector<int> &data,vector<int> &copy,int start,int end){if(start==end){copy[start]=data[start];return 0;}int length=(end-start)/2;long long left=InversePairsCore(copy,data,start,start+length);long long right=InversePairsCore(copy,data,start+length+1,end); int i=start+length;int j=end;int indexcopy=end;long long count=0;while(i>=start&&j>=start+length+1){if(data[i]>data[j]){copy[indexcopy--]=data[i--];count=count+j-start-length;          //count=count+j-(start+length+1)+1;}else{copy[indexcopy--]=data[j--];}          }for(;i>=start;i--)copy[indexcopy--]=data[i];for(;j>=start+length+1;j--)copy[indexcopy--]=data[j];       return left+right+count;}
};

【剑指offer】_12 数组中的逆序对相关推荐

  1. 【LeetCode】剑指 Offer 51. 数组中的逆序对

    [LeetCode]剑指 Offer 51. 数组中的逆序对 文章目录 [LeetCode]剑指 Offer 51. 数组中的逆序对 package offer;public class Soluti ...

  2. 剑指offer:数组中的逆序对

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

  3. 剑指offer之数组中的逆序对

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

  4. 【剑指offer】数组中的逆序对

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/mmc_maodun/article/details/27520535 转载请注明出处:http:// ...

  5. 《剑指offer》-- 数组中的逆序对、最小的K个数、从1到n整数中1出现的次数、正则表达式匹配、数值的整数次方

    一.数组中的逆序对: 1.题目: 数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出 ...

  6. 剑指 Offer 51. 数组中的逆序对(归并排序做法)

    在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出: 5 限制: 0 <= ...

  7. 剑指offer T51数组中的逆序对

    case1:暴力法 class Solution {/*case1:暴力法*/public int reversePairs(int[] nums) {int len = nums.length;if ...

  8. 【LeetCode笔记】剑指Offer 51. 数组中的逆序对(Java、分治)

    题目描述 多说无益-直接冲代码吧! 思路 && 代码 1. 暴力 O(n2n^2n2) 乍一看这题目,很难不直接用暴力法冲一冲(也就双层循环的事) 但是不出意料地超时啦-想一想,O(n ...

  9. 【LeetCode】剑指 Offer 56. 数组中数字出现的次数

    [LeetCode]剑指 Offer 56. 数组中数字出现的次数 文章目录 [LeetCode]剑指 Offer 56. 数组中数字出现的次数 package offer;import java.u ...

  10. 【LeetCode】剑指 Offer 39. 数组中出现次数超过一半的数字

    [LeetCode]剑指 Offer 39. 数组中出现次数超过一半的数字 文章目录 [LeetCode]剑指 Offer 39. 数组中出现次数超过一半的数字 一.摩尔投票法 一.摩尔投票法 核心理 ...

最新文章

  1. 如何打一个FatJar(uber-jar)
  2. 基本数据类型和引用数据类型作为参数时候的问题
  3. 贼好用的 Java 工具类库,GitHub 星标 10k+,你在用吗?
  4. React as a UI Runtime(四、条件)
  5. Mybaits插入记录返回主键值
  6. JS基础:求一组数中的最大最小值,以及所在位置
  7. (转)Delaunay三角剖分
  8. iBase4J 分布式开发平台
  9. android数据绑定_Android数据绑定
  10. javascript 推拉式菜单
  11. eXosip事件总结
  12. netty 高匿ip检测_检测代理IP匿名程度的方法
  13. 熊猫的python小课怎么样_02_Python简单爬虫(熊猫直播LOL的up主,谁最强!)
  14. html messagebox确定取消,Element MessageBox弹框的详细使用
  15. 大三下了,一点感概,仅作共勉
  16. 用深度学习构造聊天机器人简介
  17. Java钉钉开发_Exception_异常总结
  18. C++计算矩阵对角线和的程序
  19. Echarts实现堆叠图
  20. 启动盘制作 rufus3.8下载

热门文章

  1. CSS3 Filter详解(改变模糊度 亮度 透明度等方法)
  2. Hadoop自学笔记(三)MapReduce简单介绍
  3. DBMS-数据库设计与E-R模型:E-R模型、约束、E-R图、E-R扩展特性、E-R图转换为关系模式、UML建模...
  4. 【USACO2006 Mar】滑雪缆车 skilift
  5. Node Express4.x 片段视图 partials
  6. UITableViewCell 选中的状态小技巧
  7. fortran语法笔记
  8. 报错Unable to resolve target android-5
  9. FC冒险岛java版_冒险岛单机版
  10. c语言self用法,C/C++知识点之Self Numbers C语言 UVA640