Leetcode每日一题打卡

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

原题

离散化树状数组:要计算一个区间中小于某个元素的个数和,可以先看每个元素的个数。比如,对于示例数组[5,2,6,1],就有如下散列表:
nums: 0 1 2 3 4 5 6 7 8 9
count: 0 1 1 0 0 1 1 0 0 0
要计算某个元素右侧小于它的总和,使用树状数组来存储每个元素的情况,从右到左遍历原数组,先计算出当前元素右侧小于它的元素个数,写入结果数组,再讲当前元素插入树状数组,完成遍历后,再反转结果数组,就得到了目标结果。
但是,由于数组中可能存在很大的元素,导致空间浪费很大,就需要使用离散化的方式,优化空间。
代码如下:

class Solution {
    vector<int> c;
    vector<int> a;
    void initi(int length) {
        c.resize(length,0);
    }
    int lowBit(int x) {
        return x&(-x);
    }
    void Update(int pos) {
        while(pos<c.size()) {
            c[pos]+=1;
            pos+=lowBit(pos);
        }
    }
    int query(int pos) {
        int res=0;
        while(pos>0) {
            res+=c[pos];
            pos-=lowBit(pos);
        }
        return res;
    }
    void discretization(vector<int>& nums) {//离散化数组
        a.assign(nums.begin(),nums.end());//将原数组元素全部复制到数组a中
        sort(a.begin(),a.end());
        a.erase(unique(a.begin(),a.end())/*元素去重*/,a.end());//删除多余的元素
    }
    int getId(int x) {
        return lower_bound/*返回数值第一个出现的位置*/(a.begin(),a.end(),x)-a.begin()+1;
    }
public:
    vector<int> countSmaller(vector<int>& nums) {
        vector<int> res;
        discretization(nums);
        int n=nums.size();
        initi(n+5);
        for(int i=n-1;i>=0;i--) {
            int id=getId(nums[i]);//求出这个数离散化后的值
            res.push_back(query(id-1));//查找比这个数小的数的总和,压入结果数组
            Update(id);//这个数插入树形数组中
        }
        reverse(res.begin(),res.end());//得到的结果是反的,需要反转数组
        return res;
    }
};

时间复杂度O(nlogn),空间复杂度O(n)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值