力扣315 计算右侧小于当前元素的个数

题意

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元素的数量。

题解

可以将数组nums中的数组先离散化、去重。用树状数组维护这些数字出现的次数,区间[0,l]就代表了比l小的数字出现了多少次。
我们从后往前遍历原数组,每次进行单点更新和区间查询操作。

class Solution {
public:
    int c[10010],t;
    map<int,int>mp;
    vector<int>v;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int i,int  k)
    {
        while(i<=t)
        {
            c[i]+=k;
            i+=lowbit(i);
        }
    }
    int sum(int l)
    {
        int sum=0;
        while(l>=1)
        {
            sum+=c[l];
            l-=lowbit(l);
        }
        return sum;
    }
    vector<int> countSmaller(vector<int>& nums) {
        int n=nums.size();
        if(n==0)
            return v;
        v.resize(n);
        for(int i=0;i<n;i++)
            v[i]=nums[i];
        sort(v.begin(),v.end());
        t=0;
        mp[v[0]]=++t;
        for(int i=1;i<n;i++)
        {
            if(v[i]==v[i-1])
                continue;
            else
                mp[v[i]]=++t;         
        }
        for(int i=n-1;i>=0;i--)
        {
            update(mp[nums[i]],1);
            v[i]=sum(mp[nums[i]]-1);
        }
        return v;
    }
};

类似这种思想还可以用到树状数组求逆序数上。将原数组离散化后,从前往后依此加入到树状数组中(单点更新),每次区间查询可以找到比当前数字小的数字总数p,用当前遍历的i-p即可找到比其大的数。

posted @ 2020-07-22 12:16  blueattack  阅读(160)  评论(0编辑  收藏  举报