class RangeModule {
public RangeModule() {
// Write your solution here
}
public void addRange(int left, int right) {
}
public boolean queryRange(int left, int right) {
return false;
}
public void removeRange(int left, int right) {
}
}
#include <vector>
using namespace std;
class RangeModule {
public:
RangeModule() {
// Write your solution here
}
void addRange(int left, int right) {
}
bool queryRange(int left, int right) {
return false;
}
void removeRange(int left, int right) {
}
};
class RangeModule {
constructor() {
// Write your solution here
}
addRange(left, right) {
}
queryRange(left, right) {
return false;
}
removeRange(left, right) {
}
}
Coming soon
0/10
Common Bugs to Avoid
Wrong: queryRange returns false for a range fully covered by merged intervalsIntervals are not merged correctly on addRange, leaving gaps between intervals.✅ Merge intervals by expanding boundaries when overlapping or adjacent: dp[i][w] = max(dp[i-1][w], val[i-1] + dp[i-1][w-wt[i-1]])
Wrong: queryRange returns true for a range partially removedremoveRange does not split intervals properly, leaving removed parts still tracked.✅ Split intervals at removal boundaries and remove only overlapping parts.
Wrong: queryRange returns true when no intervals existEmpty intervals list not handled; queryRange returns true by default or errors.✅ Return false if intervals list is empty or no interval covers the query range.
Wrong: TLE on large inputsLinear scan of intervals for each operation causing O(n) per call.✅ Use balanced tree or binary search to achieve O(log n) per operation.
✓
Test Cases
Focus on handling empty and minimal intervals correctly before moving on.
Ensure your merging and splitting logic is robust for overlapping and adjacent intervals.
Optimize your data structure to avoid linear scans for large inputs.
After adding [10,20), removing [14,16) splits the range into [10,14) and [16,20). Querying [10,14) returns true, [13,15) returns false because 14-15 is removed, and [16,17) returns true.
💡 Think about how intervals merge or split when adding or removing ranges.
💡 Use binary search or a balanced tree to efficiently find overlapping intervals.
💡 When removing, split existing intervals if partially overlapped; when adding, merge overlapping intervals.
Why it failed: Basic case failed - likely incorrect merging or splitting of intervals during addRange or removeRange. Fix by carefully updating intervals to merge overlapping ones on add and split on remove.
✓ Core interval merging and splitting logic is correct.
After adding [5,10) and [15,20), removing [7,17) removes [7,10) and [15,17). Querying [5,7) returns true, [10,15) returns false (gap), and [17,20) returns true.
💡 Consider how removeRange affects multiple intervals that partially overlap.
💡 Check that intervals are split correctly when removal overlaps partially.
💡 Ensure queryRange returns false if any part of the queried range is missing.
Why it failed: Failed to split intervals correctly on removeRange causing incorrect query results. Fix by splitting intervals at removal boundaries properly.
✓ Intervals split and queries handled correctly.
t2_01edge
Input["queryRange(0, 1)"]
Expected["false"]
⏱ Performance - must finish in 2000ms
No ranges added; querying any range should return false.
💡 What happens if no ranges are added and queryRange is called?
💡 Check that queryRange returns false if no intervals exist.
💡 Initialize your data structure to handle empty state gracefully.
Why it failed: Empty input test failed - likely queryRange returns true or errors when no intervals exist. Fix by returning false if intervals list is empty.
Querying exact boundary intervals returns true before removal and false after removal.
💡 Test querying intervals that exactly match existing intervals.
💡 Check that addRange merges intervals correctly at boundaries.
💡 Ensure removeRange removes entire intervals when boundaries match.
Why it failed: Exact boundary test failed - intervals not merged or removed correctly at boundaries. Fix by careful boundary checks in addRange and removeRange.
Adding a range completely inside an existing range should not change intervals; queryRange returns true.
💡 Check that adding a range inside an existing interval does not create duplicates.
💡 Avoid adding redundant intervals.
💡 Merge intervals properly to maintain minimal representation.
Why it failed: Failed to handle adding range inside existing interval causing duplicates or gaps. Fix by merging intervals and ignoring redundant adds.
Large range add and remove operations with queries test O(log n) complexity; n=5 calls but with large intervals to test performance of interval merging and splitting.
💡 Use balanced tree or binary search to achieve O(log n) per operation.
💡 Avoid scanning all intervals linearly for each operation.
💡 Implement interval merging and splitting efficiently with binary search.
Why it failed: TLE due to O(n) linear scans per operation. Fix by using balanced tree or binary search to achieve O(log n) complexity.
✓ Efficient O(log n) complexity confirmed.
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
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.
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.
Final Answer:
Option A -> Option A
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. Given the following code snippet for the optimal Twitter design, what is the output of getNewsFeed(1) after these operations?
Assume getNewsFeed returns a list of tweetIds sorted from most recent to oldest.
easy
A. [6]
B. [5, 6]
C. [5]
D. [6, 5]
Solution
Step 1: Trace postTweet calls
User 1 posts tweet 5 at time=1, user 2 posts tweet 6 at time=2.
Step 2: Trace getNewsFeed(1)
User 1 follows user 2, so heap contains tweets with times 1 (tweet 5) and 2 (tweet 6). Max heap pops tweet 6 first, then tweet 5.
Final Answer:
Option D -> Option D
Quick Check:
Heap orders tweets by descending time, so output is [6, 5] [OK]
Hint: Heap orders tweets by negative time for max behavior [OK]
Common Mistakes:
Returning tweets in posting order instead of time order
Ignoring followees' tweets
3. You need to design a cache that evicts the least frequently used item when full, and among items with the same frequency, evicts the least recently used one. Which approach guarantees O(1) average time complexity for both get and put operations?
easy
A. Using a simple hash map with frequency counts and sorting keys on each eviction
B. Maintaining a frequency map of doubly linked lists to track keys by frequency and recency
C. Using a min-heap keyed by frequency and timestamp to evict the least frequently used item
D. Using a single doubly linked list ordered by frequency and recency
Solution
Step 1: Understand the eviction criteria
The cache must evict the least frequently used key, and if multiple keys share the same frequency, evict the least recently used among them.
Step 2: Identify data structures supporting O(1) operations
A frequency map with doubly linked lists allows grouping keys by frequency and maintaining recency order within each frequency group, enabling O(1) updates and eviction.
Final Answer:
Option B -> Option B
Quick Check:
Frequency map + doubly linked lists is the classic LFU O(1) approach [OK]
Single list can't maintain frequency and recency efficiently
4. Examine the following buggy remove method from the optimized Insert Delete GetRandom O(1) with duplicates data structure. Which line contains the subtle bug that can cause incorrect behavior or runtime errors?
def remove(self, val: int) -> bool:
if val not in self.idx_map or not self.idx_map[val]:
return false
remove_idx = self.idx_map[val].pop()
last_val = self.nums[-1]
self.nums[remove_idx] = last_val
self.idx_map[last_val].add(remove_idx)
# BUG: missing discard of old index for last_val
self.nums.pop()
if not self.idx_map[val]:
del self.idx_map[val]
return true
medium
A. Missing line to discard old index of last_val from idx_map[last_val]
B. Line adding remove_idx to idx_map[last_val] (self.idx_map[last_val].add(remove_idx))
C. Line popping remove_idx from idx_map[val] (remove_idx = self.idx_map[val].pop())
D. Line removing the last element from nums (self.nums.pop())
Solution
Step 1: Understand index updates during removal
When swapping last_val into remove_idx, we must update idx_map[last_val] by adding remove_idx and discarding the old index (len(nums)-1).
Step 2: Identify missing discard
The code adds remove_idx to idx_map[last_val] but does not discard the old index, causing stale indices and incorrect removals later.
Final Answer:
Option A -> Option A
Quick Check:
Missing discard leads to incorrect index tracking [OK]
Hint: Always discard old indices after swapping during removal [OK]
Common Mistakes:
Forgetting to discard old index after swap
Removing wrong element from idx_map
Incorrect pop from idx_map[val]
5. Suppose the stack is modified to allow reusing popped elements by pushing them back later, and the increment operation must still work correctly. Which modification to the optimal lazy increment approach is necessary to maintain correctness?
hard
A. Store increments per element rather than per index, requiring a more complex data structure.
B. Reset the entire increments array to zero on each push to avoid stale increments.
C. Track increments with a stack of (index, increment) pairs and apply them on pop accordingly.
D. No change needed; the existing lazy increment array works correctly with reused elements.
Solution
Step 1: Understand reuse impact
Reusing popped elements means the same stack positions may hold different elements over time, so increments per index become invalid.
Step 2: Modify increment tracking
To maintain correctness, increments must be tracked per element, not per index, requiring a data structure that associates increments with elements themselves.
Final Answer:
Option A -> Option A
Quick Check:
Per-element increments prevent stale increment application on reused positions [OK]
Hint: Reusing elements breaks index-based increments; track per element [OK]