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

本文介绍了一种在O(n log n)时间复杂度内计算逆序对数量的方法。通过将数组拆分为有序子数组,并使用双指针技巧来计算逆序对的数量,最后通过合并过程完成整个数组的排序与逆序对计数。
这个题目如果没有限制你的时间复杂度,那么它的在O(n 2) 里面完成的话, 那么就很简单 了。
但是如果发求你在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) 图相似了。

171922445795094.png看代码:

   
  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
171922445795094.png 测试代码

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












转载于:https://www.cnblogs.com/yml435/p/4655472.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值