剑指offer-数组中的逆序对

题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数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

思路就是用归并排序,在排序的过程中记录当左下标所指的数大于右下标所指的数时,说明这右下标-m这段数都是逆序对,因此加上他们的个数。
值得注意的是,这里的归并排序合并的时候比较要从大往小进行比较,因为从小到大比较在累加时会有重复非常麻烦。

另外说说归并排序,很多算法中的归并排序在每轮归并的时候都开了n个数的数组,实际上最多只需要每轮(n+1)/2个数的数组就行了,另外在排序中还有复制的过程产生了O(n)的时间复杂度,实际上也完全不必要,完全可以在原数组中重排。 只需要将原数组中的前(n+1)/2个数复制到新建立的数组中,再用新建立的数组中和原数组下标在(n+1)/2后面的数进行比较,较小值从l开始存回原数组。

但是由于这种方法在归并的时候下标从小到大比较会比较方便,否则太繁琐了,因此这题并没有进行上述优化

int  merge(vector<int> &a, int l, int m, int r)
{
    vector<int> b,c;
    int i = m, j =r,sum=0;
//  for (i = m+1; i <= r; i++) b.push_back(a[i]);
//  i = b.size()-1;
    while (i>=l && j>=m+1)
    {
        if (a[i] < a[j]) b.push_back(a[j--]);
        else
        {
            sum += j - m;
            b.push_back(a[i--]);
            if (sum >= 1000000007) sum = sum % 1000000007;
        }
    }
    if (i<l || j<m+1)
    {
        while (i >=l)
        {
            b.push_back(a[i--]);
        }
        while (j >= m + 1) b.push_back(a[j--]);
    }
    for (i = 0; i < b.size(); i++) a[l + i] = b[b.size() - i - 1];
//  cout << sum << endl;
    return sum;
}
int merge_sort(vector<int> &a, int l, int r)
{
    int result = 0;
    int m = (l + r) / 2;
    if (l >= r) return 0;
    result += merge_sort(a, l, m) % 1000000007;
    result += merge_sort(a, m + 1, r) % 1000000007;
    result += merge(a, l, m, r) % 1000000007;
    return result;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值