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
📋
Problem
Imagine you are building a version control system for an array where you can take snapshots and query historical values efficiently.
Design a SnapshotArray that supports the following interface:
- SnapshotArray(int length): Initializes an array-like data structure with the given length. Initially, each element equals 0.
- void set(index, val): Sets the element at the given index to be equal to val.
- int snap(): Takes a snapshot of the array and returns the snap_id: the total number of times snap() has been called minus 1.
- int get(index, snap_id): Returns the value at the given index, at the time the snapshot with snap_id was taken.
1 ≤ length ≤ 10^5At most 5 * 10^4 calls will be made to set, snap, and get.0 ≤ index < length0 ≤ snap_id < number of times snap() has been called0 ≤ val ≤ 10^9
Edge cases: Calling get on an index that was never set after initialization → returns 0Multiple sets on the same index before a snap → only the last set before snap is recordedCalling snap multiple times without any set in between → snapshots should be distinct
</>
IDE
class SnapshotArray:
def __init__(self, length: int):
...
def set(self, index: int, val: int) -> None:
...
def snap(self) -> int:
...
def get(self, index: int, snap_id: int) -> int:
...public class SnapshotArray {
public SnapshotArray(int length) {
// ...
}
public void set(int index, int val) {
// ...
}
public int snap() {
// ...
}
public int get(int index, int snap_id) {
// ...
}
}class SnapshotArray {
public:
SnapshotArray(int length) {
// ...
}
void set(int index, int val) {
// ...
}
int snap() {
// ...
}
int get(int index, int snap_id) {
// ...
}
};class SnapshotArray {
constructor(length) {
// ...
}
set(index, val) {
// ...
}
snap() {
// ...
}
get(index, snap_id) {
// ...
}
}
public class SnapshotArray {
public SnapshotArray(int length) {
// Write your solution here
}
public void set(int index, int val) {
}
public int snap() {
return 0;
}
public int get(int index, int snap_id) {
return 0;
}
}
#include <vector>
using namespace std;
class SnapshotArray {
public:
SnapshotArray(int length) {
// Write your solution here
}
void set(int index, int val) {
}
int snap() {
return 0;
}
int get(int index, int snap_id) {
return 0;
}
};
class SnapshotArray {
constructor(length) {
// Write your solution here
}
set(index, val) {
}
snap() {
return 0;
}
get(index, snap_id) {
return 0;
}
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: Returning the last set value regardless of snap_idNot storing historical values per snap_id, ignoring snapshot versions.✅ Store (snap_id, val) pairs per index and binary search on get for correct snap_id.
Wrong: Returning 0 for all gets even after sets and snapsNot recording set operations or snap increments properly.✅ Ensure snap increments snap_id and set records values per index.
Wrong: Returning earlier set value instead of last set before snapNot overwriting multiple sets before snap for same index.✅ Update last set value for current snap_id before snap is taken.
Wrong: Index out of range error or wrong value for invalid snap_idNot validating snap_id in get method.✅ Check snap_id bounds and return 0 or error if invalid.
Wrong: TLE on large inputsUsing full snapshot copies or linear search on get.✅ Use hash map per index with binary search for get to achieve O(log m).
✓
Test Cases
Focus on base cases like unset indices and multiple sets before snap.
Think about binary search and overwriting sets before snap.
Optimize get operations with binary search to avoid TLE.
Initialize array length 3 with zeros. Set index 0 to 5. Snap returns snap_id=0. Set index 0 to 6. Get index 0 at snap_id 0 returns 5, the value at snapshot time.
💡 Think about how to store changes efficiently between snapshots.
💡 Use a data structure that records changes per index with snapshot ids.
💡 Store pairs of (snap_id, val) per index and binary search on get.
Why it failed: Returned wrong snap_id or value. Possibly storing full snapshots incorrectly or not recording last set before snap. Fix by storing changes per index and returning correct snapshot value.
✓ Correctly handles basic set, snap, and get operations.
Set index 1 to 10, snap returns 0. Set index 1 to 20, snap returns 1. Get index 1 at snap 0 returns 10, at snap 1 returns 20.
💡 Remember each snap increments snap_id by 1.
💡 Ensure multiple snaps without intermediate sets still produce distinct snap_ids.
💡 On get, find the latest set value at or before the requested snap_id.
Why it failed: Incorrect snap_id or get value returned. Possibly not incrementing snap_id correctly or not handling multiple snaps. Fix by incrementing snap_id on snap and binary searching sets per index.
n=100, O(log m) per get with m snaps must complete within 2 seconds.
💡 Use binary search to achieve O(log m) get time.
💡 Avoid storing full snapshots to save memory and time.
💡 Store changes per index with snap_id and binary search on get.
Why it failed: TLE due to O(n*m) or linear search in get. Fix by using binary search on stored snapshots per index.
✓ Algorithm runs within time limits using binary search.
Practice
(1/5)
1. Given the following Python code for merging two skylines, and the inputs left = [[1, 3], [5, 0]] and right = [[2, 4], [6, 0]], what is the merged skyline returned by mergeSkylines(left, right)?
easy
A. [[1, 3], [2, 4], [5, 0], [6, 0]]
B. [[1, 3], [5, 0], [6, 0]]
C. [[1, 3], [2, 4], [4, 0], [6, 0]]
D. [[1, 3], [2, 4], [4, 0], [5, 0], [6, 0]]
Solution
Step 1: Trace first iterations of the merge loop
Compare left[0]=(1,3) and right[0]=(2,4): 1 < 2, so x=1, h1=3, h2=0, max_h=3 -> merged=[[1,3]]
Step 2: Next iterations and final merge
Next left[1]=(5,0), right[0]=(2,4): 2 < 5, x=2, h2=4, h1=3, max_h=4 -> merged=[[1,3],[2,4]]; then right[1]=(6,0) vs left[1]=(5,0): 5 < 6, x=5, h1=0, h2=4, max_h=4 (no change), then x=6, h2=0, max_h=0 -> merged=[[1,3],[2,4],[4,0],[5,0],[6,0]] after extending remaining points.
Final Answer:
Option D -> Option D
Quick Check:
Stepwise max height updates match merged skyline [OK]
Hint: Track h1 and h2 updates carefully during merge [OK]
Common Mistakes:
Off-by-one in indices
Missing key points when heights change
2. Examine the following erase method snippet from a skiplist implementation. Which line contains a subtle bug that can cause nodes to remain in higher levels after deletion, leading to incorrect search results?
medium
A. Line initializing update array with null
B. Line where curr is moved forward after search loop
C. Line updating update[i].forward[i] to skip curr
D. Line missing adjustment of self.level after deletion
Solution
Step 1: Identify erase steps
Nodes are removed by updating forward pointers at each level where the node exists.
Step 2: Check for level adjustment
After deletion, if top levels become empty, self.level must be decreased to avoid stale levels.
Final Answer:
Option D -> Option D
Quick Check:
Missing level adjustment causes nodes to remain logically in higher levels [OK]
Hint: Always adjust max level after erase to remove empty top levels [OK]
Common Mistakes:
Forgetting to update all levels
Not decreasing max level after erase
Incorrect pointer updates
3. Consider this buggy snippet of the optimal Twitter design's getNewsFeed method:
def getNewsFeed(self, userId: int) -> list:
users = self.followees.get(userId, set()).copy()
heap = [] # max heap by time
for u in users:
head = self.userTweets.get(u, None)
if head:
heapq.heappush(heap, (-head.time, head))
result = []
while heap and len(result) < 10:
time, node = heapq.heappop(heap)
result.append(node.tweetId)
if node.next:
heapq.heappush(heap, (-node.next.time, node.next))
return result
What is the subtle bug in this code?
medium
A. The user's own tweets are not included because userId is not added to users set.
B. The heap is used as a min heap instead of max heap by pushing negative times.
C. The linked list nodes are not updated correctly after popping from the heap.
D. The followees set is copied unnecessarily causing performance overhead.
Solution
Step 1: Check inclusion of user's own tweets
The code gets followees but never adds the userId itself to the users set, so user's own tweets are excluded.
Step 2: Verify heap usage and linked list traversal
Negative times are correctly used for max heap behavior; linked list next pointers are used properly.
Final Answer:
Option A -> Option A
Quick Check:
Missing userId in users set causes incorrect feed [OK]
Hint: User's own tweets must be explicitly included in feed [OK]
Common Mistakes:
Forgetting to add userId to followees set
Misusing heap sign for max heap
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
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.
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.
Final Answer:
Option C -> Option C
Quick Check:
Divide and conquer with linear merge per level -> O(n log n) [OK]
5. Suppose the Twitter design is extended so that users can post the same tweet multiple times (tweet reuse allowed). Which modification to the optimal approach is necessary to correctly handle this scenario?
hard
A. Allow multiple TweetNode instances with the same tweetId but different timestamps in the linked list and heap.
B. Use a hash set to track unique tweetIds per user to avoid duplicates in the feed.
C. Modify the heap to store tweetIds only once, ignoring repeated posts of the same tweetId.
D. Disallow posting duplicate tweetIds by rejecting posts with existing tweetIds.
Solution
Step 1: Understand tweet reuse impact
Allowing duplicate tweetIds means multiple posts with same id but different times must be treated as distinct tweets.
Step 2: Adjust data structures
Each post creates a new TweetNode with unique timestamp; heap and linked lists handle duplicates naturally by time ordering.
Final Answer:
Option A -> Option A
Quick Check:
Multiple nodes with same tweetId but different times must be stored separately [OK]
Hint: Treat each post as unique by timestamp, even if tweetId repeats [OK]