剑指offer - 面试题51: 数组中的逆序对 - C++

好开心!看了题没思路,看了讲解。被一点通:说实际上就是归并算法,于是动手搞出来:

class Solution {
public:
    int InversePairs(vector<int> data) {
        int count = 0;
        int n = data.size();
        vector<int> tool(n);
        int h = 1;
        while(h<n) {
            MergePass(data, tool, count, n, h);
            h=h*2;
            MergePass(tool, data, count, n, h);
            h=h*2;
        }
        return count % 1000000007;
    }
    void Merge(vector<int>& data, vector<int>& tool, int& count,
               int s, int m, int t) {
        int i=s, j=m+1;
        int k=s;
        while(i<=m && j<=t) {
            if(data[i] > data[j]) {
                tool[k++] = data[j++];
                count += (m-i+1);
                if(count >= 1000000007){
                    count %= 1000000007;
                }
            } else {
                tool[k++] = data[i++];
            }
        }
        while(i<=m) tool[k++] = data[i++];
        while(j<=t) tool[k++] = data[j++];
    }
    void MergePass(vector<int>& data, vector<int>& tool, int& count,
                  int n, int h) {
        int i=0;
        while(i <= n-2*h) {
            Merge(data, tool, count, i, i+h-1, i+2*h-1);
            i += 2*h;
        }
        if(i < n-h) {
            Merge(data, tool, count, i, i+h-1, n-1);
        } else {
            for(; i<n; i++) {
                tool[i] = data[i];
            }
        }
    }
};

第一次提交过了50%,并且没通过的用例是好大的好多数,摸不到头脑,然后看了一下之前过掉的代码,加了

if(count >= 1000000007){
    count %= 1000000007;
}

就过了!

首先表扬自己,归并算法基础扎实!又快又一次过!书上讲解的合并是从大到小,从后往前,我按寻常的思路,从小到大,从前往后,也是一样的!嗨,本来好几次点开这道题,一看代码好多就吓退了,没想到还可以这样,我总是给自己惊喜!

此题题眼:归并排序过程中可以顺便统计数组中的逆序对!

一点思考:

此题笨办法复杂度是n^,那么其它nlogn的排序能否解决这个问题?好像不能。此题的解决很重要的一点是在(交换的时候)内部有序。其实我也没想得很明白,就这样吧先^ _ ^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值