数组中的逆序对(归并排序的灵活运用)



这个题目如果没有限制你的时间复杂度,那么它的在O(n2) 里面完成的话, 那么就很简单 了。

但是如果发求你在O(n)的时间复杂度里面完成。那么这还是有点挑战性的。

题目的分析:对于逆序对的理解

先看方法:

如上面的所示,对于该算法以,我们首先将数组划分成一个一个的数字(为了排序),然后拆分成了

两个己排好序的数组。

那么如何计数逆序对呢?

如上图在(a)图中:

是两个排好序的数组,一个是5,7,另一个是4,6.

我们用两个指针P1和P2,一个指向左边那么数组的未尾,一个指向右边那么数组的未尾。

于是我们比较P1和P2所指向的这两个数,由于P1指向的数大于P2指向的数,又由于我们右

边的那个数组是从小到大排好序的,于是逆序数就是P2加它左边的数=2了。然后我们将

P1指向的数放入辅助数组中,用P3指示。P1左移一位。P2保持不动

(b)图中:

由于P1比P2小,因此此时P2指向的数无用了。因为P1应该是在左边的数组中属于最大的了

于是将P2指向的数复制到P3。然后将P2左移一位。

(C)图中:

和(a) 图相似了。

看代码:

  1. #ifndef INVERT_DATA_COUNT_H
  2. #define INVERT_DATA_COUNT_H
  3. #include<iostream>
  4. int invertPairCore(int *arr,int *copy,int start,int end);
  5. int invertDataPairCount(int *arr,int Length);
  6. int invertDataPairCount(int *arr,int Length){
  7. if(arr==NULL||Length==0){
  8. return 0;
  9. }
  10. int *copy=new int[Length];
  11. /*
  12.         for(int i=0;i<Length; i++){
  13.     copy[i]=arr[i];
  14.     }
  15.     */
  16. int InverpairCountSum=invertPairCore(arr,copy,0,Length-1);
  17. delete[] copy;
  18. return InverpairCountSum;
  19. }
  20. int invertPairCore(int *arr,int *copy,int start,int end){
  21. if(start==end){
  22. copy[start]=arr[start];
  23. return 0;
  24. }
  25. int mid=(end-start)/2; //相当于归并排序,先排好序,分成两组
  26. int leftInvertPair=invertPairCore(arr,copy,start,start+mid);
  27. int rightInvertPair=invertPairCore(arr,copy,start+mid+1,end);
  28. int i=start+mid;
  29. int j=end;
  30. int indexCopy=end;
  31. int pairCount=0;
  32. //核心步骤,和图解差不多的意思。
  33. while(i>=start&&j>=start+mid+1){
  34. if(arr[i]>arr[j]){
  35. copy[indexCopy--]=arr[i--];
  36. pairCount+=j-(start+mid+1)+1;
  37. }else{
  38. copy[indexCopy--]=arr[j--];
  39. }
  40. }
  41. //对剩下的数的处理,也就是在两数组比较的时候还有剩下数据拷贝到copy数组中。
  42. for(;i>=start; --i){
  43. copy[indexCopy--]=arr[i];
  44. }
  45. for(; j>=start+mid+1; --j){
  46. copy[indexCopy--]=arr[j];
  47. }
  48. //返回值。
  49.     return pairCount+leftInvertPair+rightInvertPair;
  50. }
  51. #endif

测试代码

  1. #include"invertDataCount.h"
  2. int main(){
  3. int arr[4]={7,5,6,4};
  4. std::cout<<invertDataPairCount(arr,4);
  5. }

来自为知笔记(Wiz)

时间: 2024-10-05 11:47:46

数组中的逆序对(归并排序的灵活运用)的相关文章

剑指offer——面试题36:数组中的逆序对(归并排序)

题目: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 思路: 采用归并排序的思想,将数组中的元素分割成子数组,先统计出子数组里的逆序对的个数.同时将这些子数组的数字排成有序的 慢慢往多的合并,在合并的过程中一面统计逆序对的个数,一面合并成一个数组时将里面排好序. 和合并排序类似,时间复杂度为O(nlogn) 下面是详细代码: #include<iostream> #include<vector> usi

面试题36:数组中的逆序对(归并排序思想)

在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数.例如,有一个数组为Array[0..n] 其中有元素a[i],a[j].如果 当i<j时,a[i]>a[j],那么我们就称(a[i],a[j])为一个逆序对.在数组{7,5,6,4}中一共存在5对逆序对,分别是(7,6),(7,5),(7,4),(6,4),(5,4). 最简单的想法就是遍历每一个元素,让其与后面的元素对比,如果大于则count++,但是这样的时间复杂度是o

数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000000007 利用归并排序的思想: 归并排序的改进,把数据分成前后两个数组(递归分到每个数组仅有一个数据项),合并数组,合并时,出现前面的数组值array[i]大于后面数组值array[j]时:则前面数组array[i]~array[mid]都是大于array[j]的,count += mid+1 - i.

编程算法 - 数组中的逆序对 代码(C)

数组中的逆序对 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 在数组中的两个数字如果前面一个数字大于后面的数字, 则这两个数字组成一个逆序对. 输入一个数组, 求出这个数组中的逆序对的总数. 使用归并排序的方法, 辅助空间一个排序的数组, 依次比较前面较大的数字, 算出整体的逆序对数, 不用逐个比较. 时间复杂度: O(nlogn) 代码: /* * main.cpp * * Created on: 2014.6.12 * Author:

数组中的逆序对-剑指Offer

数组中的逆序对 题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 思路 如果扫描整个数组,每个数字跟后面的数字比较大小,整体的复杂度是O(n^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 思路:归并排序的思路.具体参考剑指

数组中的逆序对(分治)

题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 输入: 每个测试案例包括两行: 第一行包含一个整数n,表示数组中的元素个数.其中1 <= n <= 10^5. 第二行包含n个整数,每个数组均为int类型. 输出: 对应每个测试案例,输出一个整数,表示数组中的逆序对的总数. 样例输入: 4 7 5 6 4 样例输出: 5 1.直接的做法是逐个统计,复杂度是N^2, 2.可以利用归并排序的思想,在排序过程中统

【剑指Offer学习】【面试题36:数组中的逆序对】

题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 举例分析 例如在数组{7, 5, 6, 4 中, 一共存在5 个逆序对,分别是(7, 6).(7,5),(7, 4).(6, 4)和(5, 4). 解题思路: 第一种:直接求解 顺序扫描整个数组.每扫描到一个数字的时候,逐个比较该数字和它后面的数字的大小.如果后面的数字比它小,则这两个数字就组成了一个逆序对.假设数组中含有n 个数字.由于每个数字都要和O(n)个数字作

剑指Offer面试题36(Java版):数组中的逆序对

题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数 例如在数组{7,5,6,4}中,一共存在5对逆序对,分别是{7,6},{7,5},{7,4},{6,4},{5,4}. 看到这个题目,我们的第一反应就是顺序扫描整个数组.每扫描到一个数组的时候,逐个比较该数字和它后面的数字的大小.如果后面的数字比它小,则这两个数字就组成一个逆序对.假设数组中含有n个数字.由于每个数字都要和O(n)个数字做比较,因此这个算法的时间复杂度为

【BUAA 1246】数组中的逆序对

数组中的逆序对 归并算法的灵活运用 之前就听学长说这个用来算逆序对很好用 一直没有自己实现过 这次虽然比赛中没去做 赛后自己实现了出来 很有成就感! 也对归并算法透彻领悟了 真的好多算法都需要理解 而不是死记硬背 之前就是硬背过的 过一段时间就忘光了 这次彻底明白了算法执行过程 比起做出这道题 更宝贵 代码如下 #include <bits/stdc++.h> #define LL long long using namespace std; int num[111111]; int n[11