Advertisement

Design Skiplist - LeetCode 1206 Solution

Design Skiplist - Complete Solution Guide

Design Skiplist is LeetCode problem 1206, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.

Problem Statement

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: Artyom Kalinin [CC BY-SA 3.0], v

Detailed Explanation

The problem asks us to design a Skiplist data structure without using any built-in libraries. A Skiplist is a probabilistic data structure that uses multiple levels of linked lists to achieve an average O(log n) time complexity for search, add, and erase operations. It's essentially a sorted linked list with multiple 'express lanes' allowing you to skip over large portions of the list during searches and modifications. The input is a series of operations (search, add, erase) performed on the Skiplist, and the output is the result of each operation (boolean for search and erase, null for add). The constraints specify the range of numbers to be added, searched, and erased, as well as the maximum number of operations that will be performed.

Solution Approach

The solution implements a Skiplist using a multi-level linked list structure. Each node in the Skiplist has a value and an array of 'forward' pointers, one for each level. The 'head' node points to the beginning of each level. The `search`, `add`, and `erase` operations all utilize a helper function `_find_predecessors` (or equivalent in other languages) to find the predecessors of the target value at each level. This allows us to quickly locate the position to search, insert, or delete.

Step-by-Step Algorithm

  1. Step 1: **Initialization:** Create a Skiplist object with a head node, a maximum level, and a probability 'P' for level assignment. Initialize the current level of the Skiplist to 0.
  2. Step 2: **Search:** Start from the highest level and traverse the linked list until a node with a value greater than or equal to the target is found. Move down to the next lower level and repeat the process. Continue until reaching the base level (level 0). If the node at level 0 is equal to the target, the target exists, return true. Otherwise, return false.
  3. Step 3: **Add:** Find the predecessors of the new value at each level using `_find_predecessors`. Randomly determine the level of the new node. If the new node's level exceeds the current Skiplist level, update the Skiplist level. Create the new node and insert it into the Skiplist by updating the 'forward' pointers of the predecessors and the new node.
  4. Step 4: **Erase:** Find the predecessors of the value to be erased at each level using `_find_predecessors`. If the value is found at level 0, remove the node by updating the 'forward' pointers of the predecessors. Adjust the Skiplist level if the highest level is now empty. Return true if the node was erased, false otherwise.
  5. Step 5: **Random Level Generation:** The `_random_level` function determines the level of a new node probabilistically. Starting from level 1, it increases the level with probability 'P' until the maximum level is reached or a random number is greater than or equal to 'P'.

Key Insights

  • Insight 1: The core idea of Skiplist is to use multiple levels of linked lists to reduce the search space. Higher levels allow us to skip multiple nodes, speeding up search, insertion, and deletion.
  • Insight 2: Probabilistic level assignment is crucial. Nodes are assigned a level randomly, with a probability 'P' of being included in the next higher level. This ensures a balanced structure and logarithmic time complexity.
  • Insight 3: Maintaining an 'update' array during search is essential for efficient insertion and deletion. This array stores the predecessors of the target value at each level, allowing quick access to the insertion/deletion points.

Complexity Analysis

Time Complexity: O(log(n))

Space Complexity: O(n)

Topics

This problem involves: Linked List, Design.

Companies

Asked at: Pure Storage, X, eBay.