leetcode493. Reverse Pairs

题目链接leetcode493. Reverse Pairs
难度等级:hard

思路

这道题很明显是一般逆序对的变形,我们同样可以使用归并排序来解决。
对于已经排序的 a[1 … n] 和 b[1 … m]归并。我们在归并的同时,统计满足题目要求的逆序对的个数,如果存在 a[i] > 2*b[j],就此有j对逆序对(a[i], b[j])、(a[i], b[j - 1])、(a[i], b[j - 2])、、、(a[i], b[0])。那么我们对a数组从i=0到n-1扫描,查找a[i] > 2*b[j]的最大j值,然后就可以计算出所有的逆序对了。这里,统计逆序对的复杂度是O(mn)。那继续观察到一点, i从小到大扫描, 每次找到的满足条件的最大j,后发现,j是递增的, 也就是随着i的增大, 找到的j值是不会减小的,所以,对于在下一轮扫描时候, j不是从0开始遍历,而是从上一轮扫描找到的最大j值开始往后遍历j, 基于此观察, 时间复杂度为O(m + n),至于归并操作,时间复杂度也是O(m+n), 所以归并统计逆序对复杂度是O(m + n), 然后,利用分治策略的归并排序算法, 知道时间复杂度是O(nlogn)

实现

class Solution {
public:
    int merge(vector<int> & nums, int l, int m, int r) {
        if (l >= r) return 0;
        int arr[r - l + 1];

        int ll = l, rl = m + 1;
        int c = m + 1, index = 0;

        int ret = 0;
        while(ll < m + 1) {
            while(c <= r && nums[ll] > (long long)2*nums[c]) 
                c++;
            ret += (c - (m + 1));

            while(rl <= r && nums[ll] > nums[rl])
                arr[index++] = nums[rl++];
            arr[index++] = nums[ll++];
        }

        while(rl <= r) arr[index++] = nums[rl++];

        for(int i = 0; i < (r - l + 1); i++)
            nums[l + i] = arr[i];

        return ret;
    }
    int merge_sort(vector<int> & nums, int l, int r) {
        if (l >= r) return 0;

        int m = l + ((r - l) >> 1);

        int ret = 0;
        ret += this->merge_sort(nums, l, m) + this->merge_sort(nums, m + 1, r);
        ret += this->merge(nums, l, m, r);
        return ret;
    }
    int reversePairs(vector<int>& nums) {
        return this->merge_sort(nums, 0, nums.size() - 1);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值