题目leetcode315. Count of Smaller Numbers After Self
难度等级: hard
思路
首先最暴力的方法,就是二重循环遍历a[0 … (n - 1)]。对于每个a[i], 找到a[(i + 1) … (n - 1)]中比a[i]小的数的的个数。时间复杂度是n平方。优化的一个角度是,能不能地在a[(i + 1) … (n - 1)]中找到比a[i]小的数的的个数,于是想到BST,从后面遍历数组,然后插入BST中,对于每个数,先找到利用BST找到树中比该数小的数的个数,然后再将该数插入BST中。在构建BST时候,节点除了要记录节点数值外, 还要记录以该节点为根的树的节点个数,根据这个信息,可以使用分治策略很快找到比某个数小的数的个数。这里最关键的是如何使用分治找到SBT中比target小的数的个数, 如果根节点的数值 等于 target, 那么比target小的个数,就是根节点的左子树的节点个数, 如果target小于根节点数值, 那么到根节点的做子树中查找, 如果大于, 则等于根节点加上左子数节点个数在加上从右字数查找得到的个数
实现
struct Node {
int data;
int num;
Node *left, *right;
Node(int data) : data(data), num(1), left(NULL), right(NULL) {}
};
Node * insert(Node* root, int data) {
if(root == NULL)
return new Node(data);
if(root->data > data)
root->left = insert(root->left, data);
else if (root->data < data)
root->right = insert(root->right, data);
root->num++;
return root;
}
// the number of elements which < target
int search(Node * root, int target) {
if (root == NULL) return 0;
if (root->data >= target)
return search(root->left, target);
if(root->data < target){
int tmp = root->num;
if(root->right != NULL)
tmp -= root->right->num;
return tmp + search(root->right, target);
}
}
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
int size = nums.size();
vector<int> vec(size);
Node * root = NULL;
for(int i = size - 1; i >= 0; i--) {
vec[i] = search(root, nums[i]);
root = insert(root, nums[i]);
}
return vec;
}
};