力扣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即可找到比其大的数。