给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i]
的值是 nums[i]
右侧小于 nums[i]
的元素的数量。
示例:
输入: [5,2,6,1]
输出: [2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.
思路:
从最右边开始逐步构建一颗二叉搜索树
树中维护有节点的值,小于该节点的数的数量less,左右节点,相同数字的数量
在每个位置构建完成树之后,立即计算该位置小于该数的个数,由于新的点加入之后一定是处于叶节点的。
所以从根节点开始:
1.如果节点值大于目标值,那么递归到节点的左节点进行计数
2.如果节点值等于目标值,返回该节点处less的值
3.节点值小于目标值,返回节点自身数量+less+递归右节点(因为大于节点值也有可能小于目标值)
Code:
class Solution {
public:
struct node{
int small;
int val;
int self=1;
node * left=NULL;
node * right=NULL;
node(int val,int small):small(small),val(val){};
};
node* add(node* root,int val)
{
if(root==NULL)return new node(val,0);
if(val==root->val) root->self+=1;
else if(val>root->val) root->right=add(root->right,val);
else {root->left=add(root->left,val);root->small+=1;}
return root;
}
int getnum(node* root,int val)
{
if(root==NULL)return 0;
if(root->val==val)return root->small;
if(root->val<val) return root->small+root->self+getnum(root->right,val);
if(root->val>val) return getnum(root->left,val);
}
vector<int> countSmaller(vector<int>& nums) {
int n=nums.size();
if(n==0)return {};
if(n==1) return {0};
vector<int>count(n,0);
node*root=new node(nums[n-1],0);
for(int i=n-2;i>=0;i--)
{
root=add(root,nums[i]);
count[i]=getnum(root,nums[i]);
}
return count;
}
};