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);
}
相关推荐
2601_960356384 分钟前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah28 分钟前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO931 分钟前
指针的算术运算详解
java·数据结构·算法
Coder-magician36 分钟前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
垆边人似月.1 小时前
VLAN 资源池(100~200 分档)
数据结构·算法
潼心1412o2 小时前
C++初阶(长期更新)第6讲:类和对象(下)
开发语言·c++·算法
星光开发者2 小时前
基于决策树随机森林算法的小说推荐系统的设计与实现-计算机毕设【课程设计】78485
vue.js·算法·微信小程序·django·php·课程设计·express
-森屿安年-2 小时前
按身高排序
c++·算法
程序员清风2 小时前
算法与数据结构入门:复杂度、数组与链表
数据结构·算法·链表
无定义_3 小时前
Codeforces Round 1124 (Div. 2)
算法