剑指Offer第三十五题:数组中的逆序对

题目描述

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

 

输入描述:

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

数据范围:

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

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

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

示例1:

输入

1,2,3,4,5,7,0

输出

7

 

思路:

做的差点怀疑人生,唉,卡了好久,看到这题我先试了选择排序,一直成功率是百分之50,后来才知道,是数字超过上限了,也是醉了。然后尝试了归并排序,归并排序写起来不太难,之前也写过,不过还是没把这个和答案联系起来,看网上的也看晕了,可能还是太急躁,不过最后还是做出来了。

这个版本算是好理解的版本了,这里的num就是最后答案,这里的累加就在比较的时候,比如含有两组有序数列比较

[2,4,6,8,10,1,3,5,7,9]; 这里 left = 0 ; right = 9, 计算 mid = 4, 我们拿 a[1] = 4,举例,跟 a[6]=3比较,如果  a[1]>a[6],那肯定a[1]到 a[mid] (即a[4]) 的数都大于a[6],这里的个数就是 middle-i+1;

利用这个公式就能放入归并排序计算

 

 

class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.empty())
            return 0;        
        vector<int> m = data;
        int num=0;
        MyMerge(data,m,0,data.size()-1,num);
        return num;
    }
    
    void MyMerge(vector<int>&a, vector<int>&tmp,int start,int end,int &num)
    {
        if(start<end)
        {
            int mid = (start+end)/2;
            MyMerge(a,tmp,start,mid,num);
            MyMerge(a,tmp,mid+1,end,num);
            merge(a,tmp,start,mid,end,num);
        }
    }
    
    void merge(vector<int>&arr, vector<int>&m, int left,int middle,int right,int &num)
    {
        int i = left, j =middle+1, k = left;
        while(i <  middle+1 && j < right+1){
            if(arr[i]<arr[j])
                m[k++] = arr[i++];
            else{
                m[k++] = arr[j++];
                num+=middle-i+1;
                num=num>1000000007?num%1000000007:num;
            }
        }
        if(i == middle+1){
            while(j <right+1)
                m[k++] = arr[j++];
        }
        else{
            while(i < middle+1)
                m[k++] = arr[i++];
        }
        while(left<= right){
            arr[left] = m[left];
            left ++;
        }
    }   
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值