493. Reverse Pairs

493. Reverse Pairs




题目链接:493. Reverse Pairs



题意

找出给定数组中重要逆序的对数,重要逆序定义如下:i

解法

最简单的方法就是暴力穷举,对于每个位置i都遍历一遍前面的元素,看看有没有构成逆序的元素,但是这种方法肯定是会超时的。
第二种方法是用二叉搜索树,定义树节点为拥有字段value和count的类,count是树中value大于本节点的节点数目。定义insert方法将整形值插入树中,search方法搜索树中value大于参数的节点的数量。每到一个位置i处,将i前面的元素都插入二叉搜索树,然后搜索树中value值大于等于2*nums[i]+1的节点数。理想情况下二叉搜索树能将搜索复杂度降低到O(NlogN),但是在某些情况下二叉树会退化成为链表,所以还得增加自旋保持树平衡。
第三种方法是使用类似于归并排序的算法,每次将参数数组均分成两半,分别递归处理,用变量count存储分割后的小数组返回的结果,然后在未分割的大数组(起始位置为l,终止位置为r)中,从l到中间位置mid以及从位置mid+1到r两个区域都已经分别被排序,这时用i遍历左边的半个数组,用j遍历右边的半个数组,对于每个i,只要i,j位置上的元素能够构成重要逆序的话,j就自增,对于每一个i,count的增量是j离起始位置mid+1的距离,也就是说,如果前一轮i循环的时候j已经自增到r+1,本轮i循环j不再增加,count还是要加上j-(mid+1)这个增量,因为正如前面说的,区间[l,mid]已经排好了序。



代码

class Solution {
public:
    int reversePairs(vector<int>& nums) {
        return mergeCount(nums, 0, nums.size() - 1);
    }

    int mergeCount(vector<int> &nums, int l, int r) {
        if (l >= r)return 0;
        int count = 0;
        int mid = (l + r) / 2;
        count += mergeCount(nums, l, mid) + mergeCount(nums, mid + 1, r);//
        for (int i = l, j = mid + 1; i <= mid; ++i) {
            while (j <= r && (nums[i] + 0.0) / 2 > nums[j])
                ++j;
            count += j - mid - 1;//注意,这里就算前面的nums[i]使j增大到r+1,本次循环中 j 没有自增
                                            //count仍然需要加上j-mid-1,因为每一次l到mid以及mid+1到r这两个大区间内部都是排好序的
        }
        sort(nums.begin() + l, nums.begin() + r + 1);

        return count;
    }
};




算法复杂度

算法复杂度为O(nlogn)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值