给定一个整数数组(下标由 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;
}
};