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
▶
Steps
setup
Initialize dummy head, tail, and size
Create a dummy head node with value 0 and no next node. Set tail pointer to dummy and size counter to 0.
💡 Dummy head simplifies edge cases by providing a fixed start; tail pointer helps efficient tail insertions; size tracks list length for quick index validation.
Size check quickly rejects invalid indices, saving time and avoiding errors.
Practice
(1/5)
1. You need to implement a browser history feature that supports visiting new URLs, moving backward by a number of steps, and moving forward by a number of steps. Which data structure approach best supports efficient visit, back, and forward operations with minimal time complexity?
easy
A. Using a single list with an index pointer to track the current page, slicing the list on visits to discard forward history.
B. Using a queue to store all visited URLs and dequeuing when moving back or forward.
C. Using a doubly linked list where each node stores a URL and pointers to previous and next pages.
D. Using two stacks: one for back history and one for forward history, pushing and popping URLs as navigation occurs.
Solution
Step 1: Understand operation requirements
Visit must discard forward history, back and forward must move efficiently without scanning the entire history.
Step 2: Evaluate data structures
Two stacks allow O(1) amortized push/pop for visit, back, and forward, efficiently managing history and forward pages.
Final Answer:
Option D -> Option D
Quick Check:
Two stacks handle forward/back navigation efficiently [OK]
Hint: Two stacks efficiently manage back and forward navigation [OK]
Common Mistakes:
Using a single list with slicing causes O(n) visit time
Doubly linked list is correct but more complex
Queue does not support backward navigation efficiently
2. You are given a singly linked list and a value x. The task is to reorder the list so that all nodes with values less than x come before nodes with values greater than or equal to x, while preserving the original relative order within each partition. Which approach guarantees an optimal solution with O(n) time and O(1) space complexity?
easy
A. Extract all node values into arrays, reorder them, then rebuild the list.
B. Use two pointers to build two separate linked lists for nodes less than and greater or equal to x, then concatenate them.
C. Sort the entire linked list using merge sort and then split at value x.
D. Traverse the list once, rearranging nodes in-place by adjusting pointers without extra lists.
Solution
Step 1: Understand the problem constraints
The problem requires partitioning the list around value x while preserving relative order and achieving O(n) time and O(1) space.
Step 2: Evaluate approaches
Approach A uses extra arrays, so space is O(n). Approach B uses extra lists, so space is O(n). Approach D sorts the list, which is O(n log n) time. Only approach C rearranges nodes in-place in one pass with constant space.
Final Answer:
Option D -> Option D
Quick Check:
In-place rearrangement achieves O(n) time and O(1) space [OK]
Hint: In-place pointer rearrangement is O(1) space [OK]
Common Mistakes:
Assuming sorting is needed to partition
Using extra arrays or lists increases space
Believing two separate lists always use constant space
3. Identify the bug in the following code snippet implementing the optimal approach to copy a list with random pointers:
medium
A. Line assigning curr.next.random = curr.random.next misses null check for curr.random
B. In Step 3, copy_curr is never advanced, causing incorrect separation
C. In Step 1, new_node is linked incorrectly to curr.next
D. The function returns copy_head before fully separating the lists
Solution
Step 1: Analyze Step 3 separation loop
copy_curr is initialized but never advanced inside the loop, so copied list links are not updated correctly.
Step 2: Identify fix
Adding copy_curr = copy_curr.next inside the loop after updating copy_curr.next fixes the bug.
Final Answer:
Option B -> Option B
Quick Check:
Without advancing copy_curr, copied list remains partially linked [OK]
Hint: Check if both original and copy pointers advance in separation loop [OK]
Common Mistakes:
Forgetting to advance copy_curr in separation
Assuming random pointer null checks are missing (they are present)
Mislinking new_node in Step 1 (correct here)
4. What is the space complexity of the recursive reorder list approach that uses a helper function with recursion to reorder the list in place?
medium
A. O(n) -- recursion stack uses space proportional to list length
B. O(1) -- only constant extra pointers used
C. O(log n) -- recursion depth is halved each call
D. O(n^2) -- due to repeated pointer updates in recursion
Solution
Step 1: Identify recursion depth
The helper function recurses once per node, so recursion depth is n.
Step 2: Calculate space usage
Each recursive call adds stack frame, so total space is O(n), not constant or logarithmic.
Final Answer:
Option A -> Option A
Quick Check:
Recursion stack proportional to list length [OK]
Hint: Recursion depth equals list length -> O(n) space [OK]
Common Mistakes:
Assuming constant space due to in-place changes
Confusing recursion depth with log n
Overestimating to quadratic space
5. Suppose the partition problem is modified so that nodes can be reused multiple times (e.g., the list represents a multiset with unlimited copies). Which modification to the optimal in-place partition algorithm correctly handles this scenario without breaking the algorithm?
hard
A. Convert the list to arrays, partition values, then rebuild the list to handle duplicates safely.
B. Use the same in-place pointer rearrangement but skip nodes already processed to avoid infinite loops.
C. Modify the algorithm to clone nodes when moving them to the less-than-x partition to preserve original nodes.
D. Use two separate lists with dummy heads and append clones of nodes to handle reuse.
Solution
Step 1: Understand the reuse constraint
Nodes can be reused multiple times, so in-place rearrangement that moves nodes breaks because nodes are unique objects.
Step 2: Evaluate modifications
In-place rearrangement cannot handle duplicates without cloning. Cloning in-place is complex and error-prone. Using arrays to store values and rebuild the list handles duplicates safely and cleanly.
Step 3: Compare cloning approaches
Cloning nodes in-place or in two lists adds complexity and risks pointer errors. Arrays simplify the problem.
Final Answer:
Option A -> Option A
Quick Check:
Rebuilding from arrays safely handles duplicates and reuse [OK]
Hint: Rebuild list from arrays to handle node reuse safely [OK]