Practice
Solution
Step 1: Understand problem requirements
The data structure must efficiently support set, snap, and get operations with many snapshots and updates.Step 2: Evaluate approaches
Storing full snapshots (B) uses too much space and is slow for many snaps. A global hash map with linear search (C) makes get operations slow. Segment trees (D) are complex and not optimal here. Using a hash map per index with binary search (A) allows O(1) amortized set and snap, and O(log m) get, balancing time and space efficiently.Final Answer:
Option B -> Option BQuick Check:
Binary search per index enables fast retrieval [OK]
- Thinking full snapshots are efficient for many snaps
- Using linear search for get causes slow queries
def copyRandomList(head):
if not head:
return None
curr = head
# Step 1: Insert copied nodes
while curr:
new_node = Node(curr.val, curr.next)
curr.next = new_node
curr = new_node.next
# Step 2: Assign random pointers
curr = head
while curr:
if curr.random:
curr.next.random = curr.random # Bug here
curr = curr.next.next
# Step 3: Separate lists
curr = head
copy_head = head.next
copy_curr = copy_head
while curr:
curr.next = curr.next.next
if copy_curr.next:
copy_curr.next = copy_curr.next.next
curr = curr.next
copy_curr = copy_curr.next
return copy_headSolution
Step 1: Analyze random pointer assignment
The line assignscurr.next.random = curr.random, butcurr.randompoints to original nodes, not copied nodes.Step 2: Correct assignment
It should becurr.next.random = curr.random.nextto point to the copied node corresponding tocurr.random.Final Answer:
Option A -> Option AQuick Check:
Incorrect random pointer assignment breaks copied list correctness [OK]
- Assigning random pointer directly to original node
- Mixing original and copied nodes after weaving
- Forgetting to advance curr by two nodes
get method. Which line contains the subtle bug that can cause incorrect eviction behavior?
def get(self, key: int) -> int:
if key not in self.key_val_freq:
return -1
val, freq = self.key_val_freq[key]
del self.freq_keys[freq][key]
if not self.freq_keys[freq]:
del self.freq_keys[freq]
# BUG: missing update of min_freq here
self.freq_keys[freq + 1][key] = None
self.key_val_freq[key] = (val, freq + 1)
return val
What is the bug?Solution
Step 1: Identify the role of min_freq
min_freq tracks the smallest frequency present in the cache, needed for correct eviction.Step 2: Check frequency list deletion
When freq_keys[freq] becomes empty and is deleted, if freq equals min_freq, min_freq must be incremented to freq + 1.Final Answer:
Option A -> Option AQuick Check:
Missing min_freq update causes stale min_freq and wrong eviction [OK]
- Forgetting to update min_freq after freq list deletion
- Confusing key deletion with frequency list deletion
- Assuming min_freq updates automatically
get and put operations in an optimal LRU Cache implementation using a hash map and a doubly linked list with capacity n?Solution
Step 1: Analyze get operation
Hash map provides O(1) access to node; doubly linked list allows O(1) removal and insertion to update usage order.Step 2: Analyze put operation
Insertion involves hash map update and linked list insertion/removal, all O(1). Eviction removes tail node in O(1).Final Answer:
Option B -> Option BQuick Check:
Both get and put run in constant time using combined data structures [OK]
- Assuming list removal is O(n)
- Confusing amortized with worst-case
- Thinking linked list needs balancing
addRange method for the RangeModule. Which line contains the subtle bug that causes incorrect interval merging?
def addRange(self, left: int, right: int) -> None:
i = bisect_left(self.starts, left)
j = bisect_right(self.starts, right)
if i != 0 and self.intervals[self.starts[i-1]] > left:
i -= 1
left = min(left, self.starts[i])
if j != 0:
right = max(right, self.intervals[self.starts[j-1]])
for k in self.starts[i:j]:
del self.intervals[k]
self.starts[i:j] = [left]
self.intervals[left] = right
Solution
Step 1: Analyze the condition for merging overlapping intervals
The condition uses > instead of >=, so intervals that exactly touch at the boundary are not merged.Step 2: Consequence of the bug
This causes fragmented intervals and incorrect query results because adjacent intervals are not merged properly.Final Answer:
Option A -> Option AQuick Check:
Using > instead of >= misses boundary merges [OK]
- Using strict inequality instead of inclusive for merging intervals
