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

来源:互联网 发布:linux rpm 安装目录 编辑:程序博客网 时间:2024/05/22 01:37
题目:在数组中的两个数字如果前面饿一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
例如在数组{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;}elsetemp[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;elsecout<<result<<endl;system("pause");return 0;}
运行结果:






0 0