[C++] LeetCode 493. 翻转对

题目

给定一个数组 nums ,如果 i < jnums[i] > 2*nums[j]我们就将 (i, j)称作一个重要翻转对。
你需要返回给定数组中的重要翻转对的数量。
示例 1:
这里写图片描述
示例 2:
这里写图片描述
注意:
1. 给定数组的长度不会超过50000。
2. 输入数组中的所有数字都在32位整数的表示范围内。

题解

这道题目用树状数组加上hash来做。关于树状数组的介绍可以看树状数组百度百科 或者 树状数组
这里树状数组用来计数,表示当前索引对应的值出现的次数。由于数组元素是32位整型,如果直接开一个数组包含nums中所有元素的话(考虑到边界值),数组会很大,且效率很低,考虑题目中给出nums大小不超过50000,所以可以建立一个hash映射,将原始数组排序后映射为有序的索引值,由于题目中考虑的是nums[i] > 2*nums[j],所以原始数组中元素的2倍的值也需要同时映射。
映射好了之后遍历原始数组,对每个元素的2倍值,统计当前大于该值出现的总次数,即考虑树状数组中2*nums[i]对应的索引值右侧元素出现的次数和。

代码

class Solution {
public:
    int lowbit(int x){
        return (int)x&(-1*x);
    }
    int getSum(int x,vector<int> &c){
        int sum=0;
        for(int i=x;i>0;i-=lowbit(i)){
            sum+=c[i];
        }
        return sum;
    }

    void update(vector<int> &c,int x,int v){
        for(int i=x;i<c.size();i+=lowbit(i)){
            c[i]+=v;
        }
    }

    int reversePairs(vector<int>& nums) {
        int maxN=(INT_MAX)/2,minN=(INT_MIN)/2;
        set<int> ss;
        for(auto t:nums){
            ss.insert(t);
            if(t<=maxN&&t>=minN)
                ss.insert(t*2);
        }
        unordered_map<int,int> m;
        int n=ss.size();
        auto it=ss.begin();
        for(int i=1;i<=n;i++){
            m[*it]=i;
            it++;
        }
        vector<int> sum(n+1,0);
        int res=0;
        for(auto t:nums){
            if(t<minN) res+=getSum(n,sum);
            else if(t<maxN){
                int idx=m[2*t];
                res+=(getSum(n,sum)-getSum(idx,sum));
            }
            update(sum,m[t],1);
        }
        return res;
    }
};

提交结果

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值