1. 程式人生 > 實用技巧 >力扣315 計算右側小於當前元素的個數

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