Leetcode Datastruct

紀錄一些在Leetcode上關於Datastruct有去的題目

SkipList

Leetcode 1206

  • 定義初始結構
    static const int level = 6;
    
    struct Node {
      int val;
      vector<Node*> next;
      Node(int v) : val(v) {
        next.resize(level, NULL);
      }
    }*head;
 
    Skiplist() {
      head = new Node(-1);       
    }
 
    ~Skiplist() {
      auto p = head;
      while(p != NULL) {
        auto nextNode = p->next[0];
        delete p;
        p = nextNode;
      }
    }
 
  • 最主要的輔助函數
    • find函數會找到該層中小於target的最大節點
    void find(int target,vector<Node*>&pre) {
      auto p = head;
      for(int i=level-1;i>=0;i--){
        while(p->next[i] != NULL && p->next[i]->val < target)
          p = p->next[i];
        pre[i] = p; // 代表找到該層的最大節點為p
      }
    }
  • insert函數
    void add(int num) {
        vector<Node*> pre(level);
        find(num,pre); //找到該層小於num的最大節點
        auto newNode = new Node(num);
        for(int i=0;i<level;i++){
          // 大節點插入右側
          newNode->next[i] = pre[i]->next[i];
          pre[i]->next[i] = newNode;
          if(rand() % 2) break; // 每層level都有50%的機率插入level+1,假設沒中就直接退出
        }
    }
 
  • search函數
 
    bool search(int target) {
        vector<Node*> pre(level);
        find(target,pre);
        auto p = pre[0]->next[0]; //第0層會存所有的node,因此只要確認到該層中有沒有該節點即可(透過find)
        return p && p->val == target;
    }
  • erase函數
    bool erase(int num) {
        vector<Node*> pre(level);
        find(num,pre);
 
        auto p = pre[0]->next[0];
        if (!p || p->val != num) return false;
 
        for(int i=0; i < level && pre[i]->next[i] == p;i++) {
          pre[i]->next[i] = p->next[i];
        }
 
        delete p;
 
        return true;
    }