时间效率与空间效率的平衡-面试题36-数组中的逆序对

题目描述

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

输入描述:

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

数据范围:

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

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

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


解法:

类似归并排序的过程
时间效率与空间效率的平衡-面试题36-数组中的逆序对_第1张图片
57、46是两个逆序对,count=2;
(a)p1指向的数字大于p2指向的数字,表明数组中存在逆序对。p2指向的数字是第二个子数组的第二个数字,因此第二个数组中有两个元素比7小,count=count+2=4,把7复制到辅助数组,向前移动p1和p3。
(b)p1指向的数字小于p2指向的数字,没有逆序对。把p2指向的数字复制到辅助数组,并向前移动p2和p3。
(c)p1指向的数字大于p2的数字,因此存在逆序对。类似(a)


Code:

class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.size()<=1)return 0;
        vector<int> copy=data;
        return helper(data,copy,0,data.size()-1);
    }
    int helper(vector<int> &data,vector<int> &copy,int first,int last){
        if(first==last){
            copy[first]=data[first];
            return 0;
        }
        int mid=(first+last)>>1;
        int leftCount=helper(copy,data,first,mid);
        int rightCount=helper(copy,data,mid+1,last);
        
        int i=mid;    //前半段最后一个元素
        int j=last;   //后半段最后一个元素
        int count=0;
        int indexCopy=last;
        while(i>=first && j>=mid+1){
            if(data[i]>data[j]){
                count+=j-mid;
                copy[indexCopy--]=data[i--];
                if(count>=1000000007)//数值过大求余
                {
                    count%=1000000007;
                }
            }
            else{
                copy[indexCopy--]=data[j--];
            }
        }
        while(i>=first)
            copy[indexCopy--]=data[i--];
        
		while(j>=mid+1)
            copy[indexCopy--]=data[j--];
        return (count+leftCount+rightCount)%1000000007;
    }
};


你可能感兴趣的:(剑指offer)