《剑指offer》:[36]数组中的逆序对

题目:在数组中的两个数字如果前面饿一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
例如在数组{7,5,6,4}中就有5对,{7,5},{7,6},{7,4},{5,4},{6,4}。

方案一:最直接的方法就是顺序扫描每个数字,然后和后面的数字进行比较,如果前一个比后一个小,则说明它们是逆序的,如以上的5组都是逆序的。计数器+1;每个数字和后面比较的次数是O(N),
有N个数 ,所以其时间复杂度为O(N*N)。

方案二:时间复杂度为O(N*logN)+O(N)的辅助空间。O(N*logN)是因为我们用的归并排序的思想来进行的。具体分析过程如下:



      为什么要排序,因为我们在合并的过程中,每一步都统计了逆序数,统计过了就不需要再统计了,所以就要排序,否则就重复了。最后的到的辅助空间里的元素是全部排好序的。也正是通过排序这个过程我们才能正确统计逆序数。

具体实现代码如下:

#include <iostream>
using namespace std;
bool IsInputInvalid=false;
int InversePairsHelp(int *arr,int *temp,int low,int high)
{
	if (low == high)
	{
		temp[low] = arr[high];
		return 0;
	}
	int mid = (high +low) / 2;
	int left = InversePairsHelp( temp, arr,low,  mid);  //使arr的左边有序;
	int right = InversePairsHelp(temp, arr, mid+1, high);//使arr的右边有序;
	int i = mid;
	int j = high;
	int indexCopy = high;
	int count = 0;
	while (i>=low && j>=mid+1)
	{
		if (arr[i] > arr[j])
		{
			temp[indexCopy--] = arr[i--];
			count += j -  mid;
		}
		else
			temp[indexCopy--] = arr[j--];
	}
	for (; i >= low; --i)
		temp[indexCopy--] = arr[i];
	for (; j >= mid + 1; --j)
		temp[indexCopy--] = arr[j];
	return left + right + count;
}
int InversePairs(int *arr,int length)
{
	if(NULL==arr || length<=0)
	{
		IsInputInvalid=true;
		return 0;
	}
	int *temp=new int[length];
	for(int i=0;i<length;i++)
		temp[i]=0;


	int count=InversePairsHelp(arr,temp,0,length-1);
	delete[] temp;
	return count;
}
int main()
{
	int array[4]={7,5,6,4};
	int result=InversePairs(array,4);
	if(IsInputInvalid)
		cout<<"THE INPUT IS INVALID!"<<endl;
	else
		cout<<result<<endl;
	system("pause");
	return 0;
}
运行结果:






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值