剑指offer---数组中的逆序对

115 篇文章 0 订阅
67 篇文章 1 订阅

题目描述

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

输入描述:

题目保证输入的数组中没有的相同的数字

数据范围:

	对于%50的数据,size<=10^4

	对于%75的数据,size<=10^5

	对于%100的数据,size<=2*10^5

示例:

输入:
1,2,3,4,5,6,7,0
输出:
7

解题思路:
该题数组的size<=2*10^5,那么使用两层for循环就会出现超时的情况
那么可以使用归并排序思想来实现:
因为每次归并的时候,左边和右边的数组都是有序数组,
若左边的数组中的数字大于右边的数字,那么左边从当前位置起,到左边数组结束的长度,都可以与右边的数字组成逆序对。

如:

左边为4,6     右边为3,7
那么当43比较时,(4,3),(6,3)都可以组成逆序对

下面的代码就是在归并排序的基础上加了一行统计逆序对的代码。

//数组中的逆序对 
static long sum = 0;//这里需要注意为 long 类型
void mergeArray(vector<int> &v,int left,int mid,int right){
	int i = left;//左边数组的左指针
	int j = mid+1;//右边数组的左指针
	int k = 0;//临时数组的下标
	vector<int> temp(right-left+1);
	while(i <= mid && j <= right){
		if(v[i] > v[j]){
			//此时左边数组的数字大于右边数组的数字
			//可以组成逆序对
			sum += mid - i + 1; //统计逆序对
			temp[k++] = v[j++];
		}else{
			temp[k++] = v[i++];
		}
	} 
	while(i <= mid){
		temp[k++] = v[i++];
	}
	while(j <= right){
		temp[k++] = v[j++];
	}
	for(int m = 0;m < temp.size();m++){
		v[left+m] = temp[m];
	}
}
void divide(vector<int> &v,int left,int right){
	if(left < right){
		int mid = left + (right-left) >> 1;
		divide(v,left,mid);
		divide(v,mid+1,right);
		mergeArray(v,left,mid,right);
	}
}
int InversePairs(vector<int> data){
	if(data.empty()){
		return 0;
	}
	divide(data,0,data.size()-1);
	return sum % 1000000007;
} 

其他的排序算法代码实现:

排序算法汇总—C++实现各个排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值