Bird
Raised Fist0
Interview Prepcustom-data-structureshardAmazonGoogle

All O(1) Data Structure (Max/Min Count)

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
</>
IDE
def inc(self, key: str) -> None; def dec(self, key: str) -> None; def getMaxKey(self) -> str; def getMinKey(self) -> strpublic void inc(String key); public void dec(String key); public String getMaxKey(); public String getMinKey()void inc(string key); void dec(string key); string getMaxKey(); string getMinKey()function inc(key); function dec(key); function getMaxKey(); function getMinKey()
class AllOne:
    def __init__(self):
        pass
    def inc(self, key: str) -> None:
        pass
    def dec(self, key: str) -> None:
        pass
    def getMaxKey(self) -> str:
        pass
    def getMinKey(self) -> str:
        pass
class AllOne {
    public AllOne() {
    }
    public void inc(String key) {
    }
    public void dec(String key) {
    }
    public String getMaxKey() {
        return "";
    }
    public String getMinKey() {
        return "";
    }
}
#include <string>
using namespace std;

class AllOne {
public:
    AllOne() {
    }
    void inc(string key) {
    }
    void dec(string key) {
    }
    string getMaxKey() {
        return "";
    }
    string getMinKey() {
        return "";
    }
};
class AllOne {
    constructor() {
    }
    inc(key) {
    }
    dec(key) {
    }
    getMaxKey() {
        return "";
    }
    getMinKey() {
        return "";
    }
}
Coming soon
0/10
Common Bugs to Avoid
Wrong: "" for getMaxKey/getMinKey when keys existNot updating or maintaining counts and buckets after inc/dec operations.Ensure keys are added to count buckets on inc and removed or moved on dec; update max/min pointers accordingly.
Wrong: Returning stale max/min keys after decrement removes keysFailing to remove keys from data structure when count reaches zero.Delete keys from counts and buckets when count reaches zero and update max/min pointers.
Wrong: Wrong max/min keys due to greedy selection ignoring countsSelecting keys based on insertion order or last updated rather than counts.Always select keys from buckets with max or min counts, not based on insertion order.
Wrong: TLE on large inputUsing linear scans to find max/min keys instead of O(1) data structure.Implement doubly linked list with hash maps to maintain buckets of keys by counts for O(1) operations.
Test Cases
t1_01basic
Input[{"op":"inc","arg":"hello"},{"op":"inc","arg":"hello"},{"op":"getMaxKey"},{"op":"getMinKey"},{"op":"dec","arg":"hello"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["hello","hello","hello","hello"]

After two increments, 'hello' count is 2, so max and min keys are 'hello'. After decrement, count is 1, so max and min keys remain 'hello'.

t1_02basic
Input[{"op":"inc","arg":"apple"},{"op":"inc","arg":"banana"},{"op":"inc","arg":"apple"},{"op":"getMaxKey"},{"op":"getMinKey"},{"op":"dec","arg":"apple"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["apple","banana","apple","banana"]

After increments, 'apple' count is 2, 'banana' count is 1. Max key is 'apple', min key is 'banana'. After decrement of 'apple', both have count 1, so max and min keys can be either; here max is 'apple' and min is 'banana'.

t2_01edge
Input[{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["",""]

Empty data structure returns empty string for max and min keys.

t2_02edge
Input[{"op":"inc","arg":"singlekey"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["singlekey","singlekey"]

Single key incremented once; max and min keys are the same key.

t2_03edge
Input[{"op":"inc","arg":"key1"},{"op":"dec","arg":"key1"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["",""]

Decrementing a key with count 1 removes it; data structure becomes empty, so max and min keys are empty strings.

t2_04edge
Input[{"op":"inc","arg":"same"},{"op":"inc","arg":"same"},{"op":"inc","arg":"same"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["same","same"]

All elements identical; max and min keys are the same key.

t3_01corner
Input[{"op":"inc","arg":"a"},{"op":"inc","arg":"b"},{"op":"inc","arg":"c"},{"op":"inc","arg":"a"},{"op":"inc","arg":"b"},{"op":"dec","arg":"a"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["b","c"]

After operations, 'b' has count 2, 'a' and 'c' have count 1. Max key is 'b', min key is 'c'.

t3_02corner
Input[{"op":"inc","arg":"x"},{"op":"inc","arg":"x"},{"op":"dec","arg":"x"},{"op":"dec","arg":"x"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["",""]

Increment twice then decrement twice removes key 'x'; data structure empty, so max and min keys are empty strings.

t3_03corner
Input[{"op":"inc","arg":"alpha"},{"op":"inc","arg":"beta"},{"op":"inc","arg":"gamma"},{"op":"inc","arg":"beta"},{"op":"inc","arg":"gamma"},{"op":"inc","arg":"gamma"},{"op":"getMaxKey"},{"op":"getMinKey"}]
Expected["gamma","alpha"]

'gamma' count is 3, 'beta' count is 2, 'alpha' count is 1. Max key is 'gamma', min key is 'alpha'.

t4_01performance
Input[{"op":"inc","arg":"k0"},{"op":"inc","arg":"k1"},{"op":"inc","arg":"k2"},{"op":"inc","arg":"k3"},{"op":"inc","arg":"k4"},{"op":"inc","arg":"k5"},{"op":"inc","arg":"k6"},{"op":"inc","arg":"k7"},{"op":"inc","arg":"k8"},{"op":"inc","arg":"k9"},{"op":"inc","arg":"k10"},{"op":"inc","arg":"k11"},{"op":"inc","arg":"k12"},{"op":"inc","arg":"k13"},{"op":"inc","arg":"k14"},{"op":"inc","arg":"k15"},{"op":"inc","arg":"k16"},{"op":"inc","arg":"k17"},{"op":"inc","arg":"k18"},{"op":"inc","arg":"k19"},{"op":"inc","arg":"k20"},{"op":"inc","arg":"k21"},{"op":"inc","arg":"k22"},{"op":"inc","arg":"k23"},{"op":"inc","arg":"k24"},{"op":"inc","arg":"k25"},{"op":"inc","arg":"k26"},{"op":"inc","arg":"k27"},{"op":"inc","arg":"k28"},{"op":"inc","arg":"k29"},{"op":"inc","arg":"k30"},{"op":"inc","arg":"k31"},{"op":"inc","arg":"k32"},{"op":"inc","arg":"k33"},{"op":"inc","arg":"k34"},{"op":"inc","arg":"k35"},{"op":"inc","arg":"k36"},{"op":"inc","arg":"k37"},{"op":"inc","arg":"k38"},{"op":"inc","arg":"k39"},{"op":"inc","arg":"k40"},{"op":"inc","arg":"k41"},{"op":"inc","arg":"k42"},{"op":"inc","arg":"k43"},{"op":"inc","arg":"k44"},{"op":"inc","arg":"k45"},{"op":"inc","arg":"k46"},{"op":"inc","arg":"k47"},{"op":"inc","arg":"k48"},{"op":"inc","arg":"k49"},{"op":"dec","arg":"k0"},{"op":"dec","arg":"k1"},{"op":"dec","arg":"k2"},{"op":"dec","arg":"k3"},{"op":"dec","arg":"k4"},{"op":"dec","arg":"k5"},{"op":"dec","arg":"k6"},{"op":"dec","arg":"k7"},{"op":"dec","arg":"k8"},{"op":"dec","arg":"k9"},{"op":"dec","arg":"k10"},{"op":"dec","arg":"k11"},{"op":"dec","arg":"k12"},{"op":"dec","arg":"k13"},{"op":"dec","arg":"k14"},{"op":"dec","arg":"k15"},{"op":"dec","arg":"k16"},{"op":"dec","arg":"k17"},{"op":"dec","arg":"k18"},{"op":"dec","arg":"k19"},{"op":"dec","arg":"k20"},{"op":"dec","arg":"k21"},{"op":"dec","arg":"k22"},{"op":"dec","arg":"k23"},{"op":"dec","arg":"k24"},{"op":"dec","arg":"k25"},{"op":"dec","arg":"k26"},{"op":"dec","arg":"k27"},{"op":"dec","arg":"k28"},{"op":"dec","arg":"k29"},{"op":"dec","arg":"k30"},{"op":"dec","arg":"k31"},{"op":"dec","arg":"k32"},{"op":"dec","arg":"k33"},{"op":"dec","arg":"k34"},{"op":"dec","arg":"k35"},{"op":"dec","arg":"k36"},{"op":"dec","arg":"k37"},{"op":"dec","arg":"k38"},{"op":"dec","arg":"k39"},{"op":"dec","arg":"k40"},{"op":"dec","arg":"k41"},{"op":"dec","arg":"k42"},{"op":"dec","arg":"k43"},{"op":"dec","arg":"k44"},{"op":"dec","arg":"k45"},{"op":"dec","arg":"k46"},{"op":"dec","arg":"k47"},{"op":"dec","arg":"k48"},{"op":"dec","arg":"k49"}]
⏱ Performance - must finish in 2000ms

n=100 operations, O(1) per operation required to pass within 2s

Practice

(1/5)
1. You need to design a data structure that supports fast search, insertion, and deletion of integers, with average logarithmic time complexity. The structure should maintain multiple levels of linked lists with probabilistic promotion of nodes to higher levels. Which approach best fits this requirement?
easy
A. A multi-level linked list with randomized node promotion (Skiplist)
B. A hash table with chaining for collision resolution
C. A balanced binary search tree like AVL or Red-Black Tree
D. A simple sorted singly linked list with linear search

Solution

  1. Step 1: Identify the need for probabilistic multi-level structure

    The problem requires average O(log n) operations with linked list structure and random promotion of nodes to higher levels.
  2. Step 2: Match with known data structures

    Only a Skiplist uses multiple levels of linked lists with randomized promotion to achieve logarithmic average time complexity.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Skiplist matches all requirements including probabilistic multi-level design [OK]
Hint: Skiplist uses multi-level linked lists with random promotion [OK]
Common Mistakes:
  • Confusing balanced BSTs with linked list structures
  • Assuming hash tables provide order-based search
  • Thinking linear lists can achieve logarithmic search
2. Consider the following Python code implementing an LRU Cache with capacity 2. After executing the sequence of operations below, what is the return value of cache.get(1)?
cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
cache.get(1)
cache.put(3, 3)
cache.get(2)
cache.put(4, 4)
cache.get(1)
cache.get(3)
cache.get(4)
easy
A. 1
B. 3
C. -1
D. 4

Solution

  1. Step 1: Trace cache state after each operation

    After put(1,1) and put(2,2), cache has keys [2 (MRU), 1 (LRU)]. get(1) moves key 1 to MRU, order: [1,2]. put(3,3) evicts LRU key 2, cache: [3,1]. get(2) returns -1 (evicted). put(4,4) evicts LRU key 1, cache: [4,3].
  2. Step 2: Evaluate get(1) after put(4,4)

    Key 1 was evicted, so get(1) returns -1.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Key 1 evicted after put(4,4), so get(1) -> -1 [OK]
Hint: Remember to update usage order on get and evict LRU on put [OK]
Common Mistakes:
  • Forgetting to move accessed node to front
  • Evicting wrong node
  • Returning wrong value after eviction
3. What is the space complexity of the optimal approach that copies a linked list with random pointers by interleaving copied nodes within the original list?
medium
A. O(1) because no extra data structures proportional to n are used
B. O(n) due to storing all copied nodes in a hash map
C. O(n) due to recursion stack in the copying process
D. O(n) because of auxiliary arrays used to track random pointers

Solution

  1. Step 1: Identify auxiliary data structures

    The optimal approach does not use hash maps or arrays; it weaves copied nodes into the original list.
  2. Step 2: Analyze space usage

    Only a few pointers are used; no extra space proportional to n is allocated, so space complexity is O(1).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    No hash maps or recursion stacks used [OK]
Hint: Interleaving nodes avoids extra space [OK]
Common Mistakes:
  • Assuming hash map is always needed, so O(n) space
  • Confusing recursion stack space with iterative approach
  • Thinking auxiliary arrays are used for random pointers
4. What is the time complexity of the divide and conquer approach to the Skyline Problem when given n buildings? Assume merging two skylines of total length m takes O(m) time.
medium
A. O(n²)
B. O(n)
C. O(n log n)
D. O(n * w) where w is the width of the skyline

Solution

  1. Step 1: Identify divide and conquer recurrence

    The algorithm splits buildings into halves recursively, then merges skylines in O(m) time where m is proportional to n.
  2. Step 2: Solve recurrence and analyze merge cost

    Recurrence is T(n) = 2T(n/2) + O(n), which solves to O(n log n). The width w does not affect complexity here.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Divide and conquer with linear merge per level -> O(n log n) [OK]
Hint: Divide and conquer recurrence T(n)=2T(n/2)+O(n) -> O(n log n) [OK]
Common Mistakes:
  • Confusing width w with n
  • Assuming quadratic due to nested loops
5. Suppose the SnapshotArray is extended to support negative indices and very large index ranges, but only a small subset of indices are ever set. Which modification best maintains efficient space and time complexity for set, snap, and get operations?
hard
A. Use a hash map keyed by index storing per-index snapshot lists with binary search for get.
B. Use a balanced binary search tree per index to store snapshots and perform get queries.
C. Store full snapshots of the entire array on each snap to simplify get operations.
D. Use a large fixed-size array indexed by offset to handle negative indices.

Solution

  1. Step 1: Consider negative and large indices

    Fixed-size arrays (A) are infeasible due to large or negative indices causing huge memory usage.
  2. Step 2: Evaluate sparse storage

    Using a hash map keyed by index (D) stores only set indices, maintaining space efficiency and enabling binary search for fast get.
  3. Step 3: Compare alternatives

    Full snapshots (C) waste space; balanced trees (B) add complexity without clear benefit over binary search on lists.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Hash map per index supports sparse, negative indices efficiently [OK]
Hint: Hash map per index handles sparse and negative indices efficiently [OK]
Common Mistakes:
  • Using large arrays wastes memory
  • Full snapshots explode space usage