LeetCode //C - 1206. Design Skiplist

1206. Design Skiplist

Design a Skiplist without using any built-in libraries.

A skiplist is a data structure that takes O(log(n)) time to add, erase and search. Comparing with treap and red-black tree which has the same function and performance, the code length of Skiplist can be comparatively short and the idea behind Skiplists is just simple linked lists.

For example, we have a Skiplist containing 30,40,50,60,70,90 and we want to add 80 and 45 into it. The Skiplist works this way:

You can see there are many layers in the Skiplist. Each layer is a sorted linked list. With the help of the top layers, add, erase and search can be faster than O(n). It can be proven that the average time complexity for each operation is O(log(n)) and space complexity is O(n).

See more about Skiplist: https://en.wikipedia.org/wiki/Skip_list

Implement the Skiplist class:

  • Skiplist() Initializes the object of the skiplist.
  • bool search(int target) Returns true if the integer target exists in the Skiplist or false otherwise.
  • void add(int num) Inserts the value num into the SkipList.
  • bool erase(int num) Removes the value num from the Skiplist and returns true. If num does not exist in the Skiplist, do nothing and return false. If there exist multiple num values, removing any one of them is fine.

Note that duplicates may exist in the Skiplist, your code needs to handle this situation.

Example 1:

Input:

"Skiplist", "add", "add", "add", "search", "add", "search", "erase", "erase", "search"

\[\], \[1\], \[2\], \[3\], \[0\], \[4\], \[1\], \[0\], \[1\], \[1\]

Output:

null, null, null, null, false, null, true, false, true, false

Explanation

Skiplist skiplist = new Skiplist();

skiplist.add(1);

skiplist.add(2);

skiplist.add(3);

skiplist.search(0); // return False

skiplist.add(4);

skiplist.search(1); // return True

skiplist.erase(0); // return False, 0 is not in skiplist.

skiplist.erase(1); // return True

skiplist.search(1); // return False, 1 has already been erased.

Constraints:
  • 0 < = n u m , t a r g e t < = 2 ∗ 10 4 0 <= num, target <= 2 * 10^4 0<=num,target<=2∗104
  • At most 5 ∗ 10 4 5 * 10^4 5∗104 calls will be made to search, add, and erase.

From: LeetCode

Link: 1206. Design Skiplist


Solution:

Ideas:

add, search, and erase all move from the highest level down to level 0, so the average time complexity is O(log n).

Code:
c 复制代码
#define MAX_LEVEL 32

typedef struct Node {
    int val;
    struct Node* forward[MAX_LEVEL];
} Node;

typedef struct {
    Node* head;
    int level;
} Skiplist;

Node* createNode(int val) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->val = val;
    for (int i = 0; i < MAX_LEVEL; i++) {
        node->forward[i] = NULL;
    }
    return node;
}

int randomLevel() {
    int level = 1;
    while ((rand() & 1) && level < MAX_LEVEL) {
        level++;
    }
    return level;
}

Skiplist* skiplistCreate() {
    Skiplist* obj = (Skiplist*)malloc(sizeof(Skiplist));
    obj->head = createNode(-1);
    obj->level = 1;
    return obj;
}

bool skiplistSearch(Skiplist* obj, int target) {
    Node* cur = obj->head;

    for (int i = obj->level - 1; i >= 0; i--) {
        while (cur->forward[i] && cur->forward[i]->val < target) {
            cur = cur->forward[i];
        }
    }

    cur = cur->forward[0];
    return cur && cur->val == target;
}

void skiplistAdd(Skiplist* obj, int num) {
    Node* update[MAX_LEVEL];
    Node* cur = obj->head;

    for (int i = obj->level - 1; i >= 0; i--) {
        while (cur->forward[i] && cur->forward[i]->val < num) {
            cur = cur->forward[i];
        }
        update[i] = cur;
    }

    int lv = randomLevel();

    if (lv > obj->level) {
        for (int i = obj->level; i < lv; i++) {
            update[i] = obj->head;
        }
        obj->level = lv;
    }

    Node* node = createNode(num);

    for (int i = 0; i < lv; i++) {
        node->forward[i] = update[i]->forward[i];
        update[i]->forward[i] = node;
    }
}

bool skiplistErase(Skiplist* obj, int num) {
    Node* update[MAX_LEVEL];
    Node* cur = obj->head;

    for (int i = obj->level - 1; i >= 0; i--) {
        while (cur->forward[i] && cur->forward[i]->val < num) {
            cur = cur->forward[i];
        }
        update[i] = cur;
    }

    cur = cur->forward[0];

    if (!cur || cur->val != num) {
        return false;
    }

    for (int i = 0; i < obj->level; i++) {
        if (update[i]->forward[i] != cur) {
            break;
        }
        update[i]->forward[i] = cur->forward[i];
    }

    free(cur);

    while (obj->level > 1 && obj->head->forward[obj->level - 1] == NULL) {
        obj->level--;
    }

    return true;
}

void skiplistFree(Skiplist* obj) {
    Node* cur = obj->head;

    while (cur) {
        Node* next = cur->forward[0];
        free(cur);
        cur = next;
    }

    free(obj);
}
相关推荐
码行山野赴时序归途1 小时前
三道经典数组题:从暴力到最优的算法思维
c语言·开发语言·数据结构·算法·leetcode
徐小夕1 小时前
3分钟从想法到Agent上线:我们开源了一款AI可视化工作流“IDE”
前端·算法·github
sel_93 小时前
【强化学习】Hands-on Modern RL项目实践|OPD 算法完整解析
人工智能·深度学习·算法·机器学习·语言模型
Navigator_Z3 小时前
LeetCode //C - 1209. Remove All Adjacent Duplicates in String II
c语言·算法·leetcode
ShineWinsu5 小时前
对于 C++:C++14中从变量模板、泛型 Lambda 到并发与字面量的解析
c++·算法
土司大王6 小时前
LeetCode hot100——合并两个有序链表
算法·leetcode·链表
码行山野赴时序归途6 小时前
算法效率的度量(上):时间复杂度中的对数思维
c语言·数据结构·算法
算AI6 小时前
基于LLM的无人机仿真测试:新方法竞赛夺佳绩
人工智能·深度学习·算法·机器学习·ai