Rank from Stream:设计一个在线算法,包含track()和getRankOfNumber()两个方法。track(int x)读取输入中的整数并存储,getRankOfNumber(int x)返回已经读取的不大于x的整数数量。
最先想到的方法就是把读取的数据按序存入数组中:
track()的逻辑就是找到第1个比x大的数,然后将这个数以及后面的数向后移动,并将x插入getRankOfNumber()的逻辑就是找到第1个比x大的数,然后返回x的下标就可以了(注意书上要求当x数存在的多个时,返回的结果不应该包含x本身的计数,也就是返回最后一个x的下标)
class StreamRank {
private:
vector<int> vec;
size_t binarySearch(const int x)
{
size_t begin = 0, end = vec.size();
while(begin < end){
size_t mid = begin + (end - begin) / 2;
if(vec[mid] <= x) begin = mid + 1;
else end = mid;
}
return begin;
}
public:
StreamRank() {
}
void track(int x) {
size_t pos = binarySearch(x);
vec.push_back(0);
for(size_t i = vec.size(); i > pos && i > 1; i--)
{
vec[i - 1] = vec[i - 2];
}
vec[pos] = x;
}
int getRankOfNumber(int x) {
return binarySearch(x);
}
};
/**
* Your StreamRank object will be instantiated and called as such:
* StreamRank* obj = new StreamRank();
* obj->track(x);
* int param_2 = obj->getRankOfNumber(x);
*/
由于上一题的下标,我一度以为二分法查找第一个大于目标值的数都不会写了。采用顺序存储时,两种算法的复杂度都可以达到O(logn),但是track()需要批量移动元素。
为了避免这一点,可以选择采用二叉搜索树的形式,其中每个节点包含子节点指针,左子树大小leftSubSize和重复次数dup,这样在查找的过程中,累加leftSubSize和dup即可。
class StreamRank {
private:
struct Node
{
int value, leftSubSize, dup;
Node* left;
Node*right;
Node(int value) : value(value), leftSubSize(0), dup(1), left(nullptr), right(nullptr){};
};
Node* root;
public:
StreamRank() {
root = nullptr;
}
void track(int x) {
Node** curr = &root;
while(*curr != nullptr){
if(x < (*curr)->value){
(*curr)->leftSubSize++;
curr = &(*curr)->left;
}
else if(x > (*curr)->value){
curr = &(*curr)->right;
}
else{
(*curr)->dup++;
return;
}
}
*curr = new Node(x);
return;
}
int getRankOfNumber(int x) {
Node** curr = &root;
int ret = 0;
while(*curr != nullptr){
if(x < (*curr)->value){
curr = &(*curr)->left;
}
else if(x > (*curr)->value){
ret += (*curr)->leftSubSize + (*curr)->dup;
curr = &(*curr)->right;
}
else{
ret += (*curr)->leftSubSize + (*curr)->dup;
return ret;
}
}
return ret;
}
};
/**
* Your StreamRank object will be instantiated and called as such:
* StreamRank* obj = new StreamRank();
* obj->track(x);
* int param_2 = obj->getRankOfNumber(x);
*/
本文介绍了一种在线算法RankfromStream的设计思路,通过两种方法实现:一是使用数组进行二分查找和元素移动;二是利用二叉搜索树,每个节点包含子节点指针、左子树大小和重复次数,实现高效查找和存储。该算法适用于处理连续输入的整数流,能够快速获取不大于特定数值的整数数量。
609

被折叠的 条评论
为什么被折叠?



