leetcode1206. Design Skiplist
Intuition
跳表。skip list。
一个 node,多个指针,相当于一行一个指针,最下面一行 base level,包含全部的元素。相当于用 rand 来实现了二分。
search。二分搜索思路。
add。rand 来决定高度(层数),遍历的是要存下 precursor,用来建节点的。
erase。可能有多个,一次只删除一个。
Solution
struct Node {
vector<Node*> forward;
int val;
Node(int val): val(val) {}
};
class Skiplist {
private:
Node* head;
Node* tail;
public:
Skiplist() {
head = new Node(0);
tail = new Node(0);
head->forward.push_back(tail);
}
bool search(int target) {
int mx = head->forward.size();
auto now = head;
for (int i = mx - 1; i >= 0; i--) {
while (now->forward[i] != tail && target > now->forward[i]->val ) {
// go right
now = now->forward[i];
}
if (now->forward[i] == tail || target < now->forward[i]->val) {
// go down
continue;
} else {
// equal
return true;
}
}
return false;
}
void add(int num) {
int mx = head->forward.size();
stack<Node*> pre;
auto now = head;
for (int i = mx - 1; i >= 0; i--) {
while (now->forward[i] != tail && num >= now->forward[i]->val ) {
// go right
now = now->forward[i];
}
// go down
pre.push(now);
}
Node* cur = new Node(num);
int coinFlip = 1;
int level = 0;
while (coinFlip) {
if (!pre.empty()) {
Node* p = pre.top(); pre.pop();
cur->forward.push_back(p->forward[level]);
p->forward[level] = cur;
} else {
cur->forward.push_back(tail);
head->forward.push_back(cur);
}
coinFlip = rand() & 1;
level++;
}
}
// memory leak!
bool erase(int num) {
int mx = head->forward.size();
auto now = head;
int find_flag = 0;
for (int i = mx - 1; i >= 0; i--) {
while (now->forward[i] != tail && num > now->forward[i]->val ) {
// go right
now = now->forward[i];
}
if (now->forward[i] == tail || num < now->forward[i]->val) {
// go down
continue;
} else {
// equal
find_flag = find_flag | 1;
// find next
Node* next = now->forward[i]->forward[i];
// while (next != tail && next->val == num) {
// next = next->forward[i];
// }
now->forward[i] = next;
}
}
for (int i = mx - 1; i > 0; i--) {
if (head->forward[i] == tail) head->forward.pop_back();
else break;
}
return find_flag;
}
};
/**
* Your Skiplist object will be instantiated and called as such:
* Skiplist* obj = new Skiplist();
* bool param_1 = obj->search(target);
* obj->add(num);
* bool param_3 = obj->erase(num);
*/
Last updated