题目:在数组中的两个数字如果前面饿一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
例如在数组{7,5,6,4}中就有5对,{7,5},{7,6},{7,4},{5,4},{6,4}。
方案一:最直接的方法就是顺序扫描每个数字,然后和后面的数字进行比较,如果前一个比后一个小,则说明它们是逆序的,如以上的5组都是逆序的。计数器+1;每个数字和后面比较的次数是O(N),
有N个数 ,所以其时间复杂度为O(N*N)。
例如在数组{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;
}
运行结果: