【33】利用归并排序求逆序数对

简介: 题目:利用归并排序求解一个数组中的逆序数对分析:1. 什么是逆序数对,例如给定数组{7, 5, 6, 4},对于每个数num,如果num之前有多少个数大于num则说明num这个数构成逆序数对有多少个    7有0个,5有1个,6有1个,4有三个,因此数组中总的逆序数对为5。


题目:利用归并排序求解一个数组中的逆序数对


分析:

1. 什么是逆序数对,例如给定数组{7, 5, 6, 4},对于每个数num,如果num之前有多少个数大于num则说明num这个数构成逆序数对有多少个

    7有0个,5有1个,6有1个,4有三个,因此数组中总的逆序数对为5。


2. 怎么利用归并排序来求逆序数对呢?

   (1)假设数组为{7, 5, 6, 4}

   (2)归并排序的递归树如下

       

   (3)求逆序数对是在合并左右两个子序列的时候。在merge函数中,左右子序列都是各自有序。

            在合并两个子序列的时候我们是从前往后枚举两个子序列,每次求两个数中的最小值存放到另一个数组中。

            假设此时左序列数为arr[i],有序列为arr[j]。

            如果arr[i] > arr[j],则可以知道左序列中从i开始到结束的所有元素都和arr[j]构成逆序数对。

            如果arr[i] <= arr[j]则无法构成逆序数对。

   (4)根据第三点,我们可以对数组{7,5,6,4}进行验证

           合并第三层:7 > 5逆序数加1;6 > 4逆序数加1。合并完第三层为(5 7) 和 (4 6)

           合并第二层:5 > 4逆序数加2;7 > 4逆序数加1。合并完第二层为(4 5 6 7)

           第一层不用合并,所以总的逆序数对为5。


3. 代码

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 1010;
int ans;

//合并左右子序列
void Merge(int *arrNum, int l, int mid, int r){
    //数据不合法 
	if(arrNum == NULL || l > r){
       return;
    }
    int i = l;
	int j = mid+1;
	int pos = l;
	int tmpArr[N]; 
	//枚举
	while((i <= mid) && (j <= r)){
        if(arrNum[i] <= arrNum[j]){
            tmpArr[pos++] = arrNum[i++];
        }
        else{
            ans += (mid-i+1);//加上逆序数对
			tmpArr[pos++] = arrNum[j++]; 
		}
	} 
	//剩下的直接插入数组末尾
	while(i <= mid){
        tmpArr[pos++] = arrNum[i++];
	} 
	while(j <= r){
        tmpArr[pos++] = arrNum[j++];
	} 
	//复制回新的数组 
	for(int k = l; k <= r; k++){
        arrNum[k] = tmpArr[k];
	}
} 

//求逆序数对 
int GetReverseNumber(int *arrNum, int l, int r){
	//数据不合法 
	if(arrNum == NULL || l >= r){
        return 0;
    }
    int mid = (l+r)>>1;
    GetReverseNumber(arrNum, l, mid);
    GetReverseNumber(arrNum, mid+1, r);
    Merge(arrNum, l, mid, r);
}
 
int main(){ 
    int arrNum[] = {7,5,6,4};
    //求逆序数对
    ans = 0;
    GetReverseNumber(arrNum, 0, 3);
    cout<<ans<<endl;
    getchar();
    return 0;
}
/*
输出
5 
*/


目录
相关文章
|
6月前
归并排序详解
归并排序详解
59 1
|
15天前
归并排序
归并排序。
19 2
|
5月前
|
算法 搜索推荐 Java
归并排序就是这么容易
归并排序就是这么容易
42 2
|
6月前
|
存储 算法 搜索推荐
C++归并排序的实现
C++归并排序的实现
|
6月前
|
搜索推荐
归并排序是什么
归并排序是什么
20 归并排序
20 归并排序
42 0
|
搜索推荐 算法 C#
C#——归并排序
C#——归并排序
156 0
|
算法
归并排序及小和问题(中)
归并排序及小和问题(中)
159 1
归并排序及小和问题(中)
|
算法
【2. 归并排序】
归并与快排不同: >快速排序: >- 分界点是随机数组里面的一个`数`来分,使得左边都是<= 这个数,右边 >= 这个数 (`数值`) >- 先分完,在分别递归俩边 > >归并排序: >- 先递归俩边,在进行合并操作 >- 分界点是`整个数组中间的位置`(`下标值`)
96 0
【2. 归并排序】