题目如下:
给定一个整数数组(下标由 0 到 n-1, n 表示数组的规模,取值范围由 0 到10000)。对于数组中的每个 ai
元素,请计算ai
前的数中比它小的元素的数量。
样例
对于数组[1,2,7,8,5]
,返回 [0,1,2,3,2]
解题时产生3个思路:
1:暴力向ai前面的元素比较扫描,复杂度最高。
2:这题目要的是前面比自己小的数的个数,那么,把它放在已排序的特化环境里显然会变得更加简单,排序后找到比ai大的元素即可解题。
3:由思路2衍生而来,通过缓存某区间点的“比其小的数个数”,从而舍去半部分已知小的数。这里使用类似二叉查找树的结构,遇大放右,遇小放左。那么ai元素在树中经历结点的所有“左节点”个数即为解。这样不但可以舍去半部分已知小的数,对重复元素的处理也会变得相对简单。
结构定义如下:
typedef struct CNODE
{
int l_count = 0, data =0, rep = 0;
CNODE *left_node=nullptr,*right_node=nullptr;
CNODE(int num) { data = num; }
~CNODE() { if (left_node)delete left_node; if (right_node) delete right_node; }
}CNODE;
思路三代码实现如下:
int* Method(vector<int> &source)
{
int count; int *res = new int[source.size()];
CNODE *temp = nullptr; res[0] = 0;
CNODE *root = new CNODE(source[0]);
for (int i = 1; i < (int)source.size(); ++i) {
temp = root; count = 0;
while (true) {
if (temp->data > source[i]) {
temp->l_count++;
if (temp->left_node)
temp = temp->left_node;
else {
temp->left_node = new CNODE(source[i]); break;
}
}
else if (temp->data < source[i]) {
count += temp->l_count + temp->rep + 1;
if (temp->right_node)
temp = temp->right_node;
else {
temp->right_node = new CNODE(source[i]); break;
}
}
else {
count += temp->l_count, temp->rep++; break;
}
}
res[i] = count;
}delete root;
return res;
}