35、数组中的逆序对

来源:互联网 发布:淘宝掌柜名能改吗 编辑:程序博客网 时间:2024/06/08 19:36

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

输入描述:
题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5

输入例子:
1,2,3,4,5,6,7,0

输出例子:
7

思路:归并排序
如下图所示(借用剑指offer书上的讲解)
这里写图片描述

这里写图片描述

我们先用两个指针分别指向两个子数组的末尾,并每次比较两个指针指向的数字。如果第一个数组中的数字大于第二个数组中的数字,则构成逆序对,并且逆序对的数目等于第二个子数组中剩余数字的个数。如果第一个数组中的数字小于或等于第二个数组中的数字,则不构成逆序对。每一次比较的时候,我们都把较大的数字从后往前复制到一个辅助数组中去,确保辅助数组中的数字是递增排序的。在把较大的数字复制到数组织后,把对应的指针向前移动一位,接下来进行下一轮比较。

代码:

class Solution {public:    long InversePairsCore(vector<int> &data,vector<int>&copy,int start,int end)    {        //注意返回值如果不用long数据不能全通过的        if(start==end)        {            copy[start]=data[start];            return 0;        }        //递归        int length = (end-start)/2;        long left = InversePairsCore(copy,data,start,start+length);        long right = InversePairsCore(copy,data,start+length+1,end);        //归并排序,并且计算本次的逆序数        int i = start + length;//前半部分指针        int j = end;//后半部分指针        int indexCopy = end;//辅助数组的指针        long  count=0;//本次逆序数的计数器        while(i>=start&&j>=start+length+1)        {            if(data[i]>data[j])            {                copy[indexCopy--]=data[i--];                count+=j-start-length;            }            else            {                copy[indexCopy--]=data[j--];            }        }        for(;i>=start;--i)            copy[indexCopy--] = data[i];        for(;j>=start+length+1;--j)            copy[indexCopy--] = data[j];        //注意返回要把递归的left和right加上        return left+right+count;        }    int InversePairs(vector<int> data) {        int length = data.size();        if(length<=0)            return 0;        vector<int> copy(data);        //for(int i=0;i<length;i++)        //    copy.push_back(data[i]);        long count = InversePairsCore(data,copy,0,length-1);        copy.clear();        return count%1000000007;    }};
原创粉丝点击