统计前面比自己小的数的个数

给定一个整数数组(下标由 0 到 n-1, n 表示数组的规模,取值范围由 0 到10000)。对于数组中的每个 ai 元素,请计算 ai 前的数中比它小的元素的数量。

样例

对于数组[1,2,7,8,5] ,返回 [0,1,2,3,2]

说明

在做此题前,最好先完成以下三道题: 线段树的构造, 线段树的查询 II,和 比给定数小的项目数 I 。

class Node
{
public:
    Node(int _start, int _end) :
        start(_start), end(_end), left(nullptr), right(nullptr),
        cnt(0) {}
    
    int start, end;
    Node *left, *right;
    int cnt;
};
    
class Solution {
public:
   /**
     * @param A: An integer array
     * @return: Count the number of element before this element 'ai' is 
     *          smaller than it and return count number array
     */
    vector<int> countOfSmallerNumberII(vector<int> &A) {
        // write your code here
        Node *root = build(0, 20000);
        vector<int> res;
        
        for (int i = 0; i < A.size(); i++)
        {
            int cnt = query(root, 0, A[i] - 1);
            res.push_back(cnt);
            modify(root, A[i]);
        }
        
        return res;
    }
private:
    Node *build(int start, int end)
    {
        if (start > end)
        {
            return NULL;
        }
        if (start == end)
        {
            return new Node(start, end);
        }
        
        int mid = start + ((end - start) >> 1);
        
        Node *root = new Node(start, end);
        root->left = build(start, mid);
        root->right = build(mid + 1, end);
        
        return root;
    }
    
    void modify(Node *root, int idx){
        if (root == NULL) 
        {
            return;
        }
        
        if (root->start == root->end && root->start == idx)
        {
            ++(root->cnt);
            return;
        }
        
        int mid = root->start + ((root->end - root->start) >> 1);
        if (mid >= idx)
        {
            modify(root->left, idx);
        }
        else
        {
            modify(root->right, idx);
        }
        
        root->cnt = root->left->cnt + (root->right ? root->right->cnt : 0);
    }
    
    int query(Node *root, int start, int end)
    {
        if (root->end < start || root->start > end)
        {
            return 0;
        }
        if (root->start >= start && root->end <= end)
        {
            return root->cnt;
        }
            
        int mid = root->start + ((root->end - root->start) >> 1);
        if (mid >= end) 
        {
            return query(root->left, start, end);
        }
        if (mid < start) 
        {
            return query(root->right, start, end);
        }
        
        int leftRes = query(root->left, start, mid);
        int rightRes = query(root->right, mid + 1, end);
        
        return leftRes + rightRes;
    }
};


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值