493. Reverse Pairs

Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j].

You need to return the number of important reverse pairs in the given array.

Example1:

Input: [1,3,2,3,1]
Output: 2

Example2:

Input: [2,4,3,5,1]
Output: 3

Note:

  1. The length of the given array will not exceed 50,000.
  2. All the numbers in the input array are in the range of 32-bit integer.
/*
  基于分治算法的思想,在归并排序的基础上寻找Reverse Pairs, 步骤如下:
  1.递归划分序列;
  2.对将要两两归并的子序列进行Reverse Pairs查找,假设两个子序列分别为a1,a2,统计Reverse Pairs个数count;
  3.归并a1,a2,得到新的有子序列,重复步骤2,3,直到得到长度与原序列相同的有序序列,返回count.
  Reverse Pairs查找方法如下:
  假设将要归并的两个子序列是a1,a2;下标i,j分别为a1,a2的下标,由于序列进行的是归并排序,因此必有i<j,即表示a1,a2各自记录的顺序不影响查找Reverse Pairs,
  对a1进行遍历,将a1的记录与a2中的记录进行比较,若满足a1[i]>a2[j]*2.0,则成功查找到Rever Pairs,子序列a2后移一位,继续和a1[i]比较.要注意到,
  只要a1中较小的记录满足查找Reverse Pairs的准则,排在该记录后的所有记录都会满足该准则,因此,不必将a1的每个记录都与a2中的所有记录进行比较. 
  Reverse Pairs个数count的统计,我们只需要在遍历a1时对a2当前记录的下标j与a2第一个记录的下标之差进行累加即可.
*/
	void merge(int* A,int* B,int low,int high){
	    int i,j,mid,k;
	    mid=(low+high)/2;
	for(i=low;i<=high;++i)
	    B[i]=A[i];
	for( k=low,i=low,j=mid+1;i<=mid&&j<=high;++k){
		if(B[i]>B[j])
		A[k]=B[j++];
		else
		A[k]=B[i++];
	}
	while(i<=mid)
    	A[k++]=B[i++];
	while(j<=high)
    	A[k++]=B[j++];
}
    int mergeSort(int* A,int* B,int low,int high){
		int count = 0;
		if(low<high){
	  		int mid=high+low;
	  		mid/=2;
	  		count = mergeSort(A,B,low,mid)+mergeSort(A,B,mid+1,high);
	  		for(int i = low,j=mid+1;i<=mid;++i){
	  			while(j<=high&&A[i]>A[j]*2.0)j++;//查找Reverse Pairs
	  			count+=j - mid - 1;//统计Reverse Pairs个数
	  		}
	  		merge(A,B,low,high);
		}
		return count;
    }
    int reversePairs(int* nums, int numsSize) {
    	int count = 0;
    	int* B = (int*)malloc(sizeof(int)*(numsSize));
    	count = mergeSort(nums,B,0,numsSize-1);//将nums的记录按从小到大的顺序进行归并排序
    	free(B);
    	B=NULL;
        return count;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值