DSA Notes
Solve 12 classic linked list interview problems with complete solutions — reorder list, add two numbers, copy list with random pointer, flatten multilevel list, rotate list, remove nth from end, odd-even linked list, merge k sorted lists, and more.
Introduction
This lesson applies everything covered in the linked list section to 12 classic interview problems. Each solution demonstrates a key pattern — the two-pointer technique, dummy head nodes, merging, reversal — and explains why the approach works.
Problem 2 — Add Two Numbers
Problem: Two non-empty linked lists represent non-negative integers in reverse order. Add the two numbers and return the sum as a linked list.
| l1: 2 | 4 → 3 (represents 342) |
| l2: 5 | 6 → 4 (represents 465) |
| Output: 7 | 0 → 8 (represents 807) |
def add_two_numbers(l1, l2):
"""
Simulate manual addition with carry.
Time: O(max(m,n)), Space: O(max(m,n))
"""
dummy = Node(0)
current = dummy
carry = 0
while l1 or l2 or carry:
val1 = l1.data if l1 else 0
val2 = l2.data if l2 else 0
total = val1 + val2 + carry
carry = total // 10
digit = total % 10
current.next = Node(digit)
current = current.next
if l1: l1 = l1.next
if l2: l2 = l2.next
return dummy.nextProblem 3 — Copy List with Random Pointer
Problem: A linked list where each node has next and random pointers. Create a deep copy.
O(1) space solution (weaving):
def copy_random_list_o1_space(head):
"""
Interleave original and copy nodes, then separate.
Time: O(n), Space: O(1)
"""
if not head:
return None
# Step 1: Insert copy nodes after each original
current = head
while current:
copy = RandomNode(current.val)
copy.next = current.next
current.next = copy
current = copy.next
# Step 2: Set random pointers for copy nodes
current = head
while current:
if current.random:
current.next.random = current.random.next
current = current.next.next
# Step 3: Separate the two lists
current = head
copy_head = head.next
copy_current = copy_head
while current:
current.next = current.next.next
copy_current.next = copy_current.next.next if copy_current.next else None
current = current.next
copy_current = copy_current.next
return copy_headProblem 4 — Reorder List
Problem: Given [L0,L1,...,Ln-1,Ln], reorder it to [L0,Ln,L1,Ln-1,L2,Ln-2,...]. In-place.
def reorder_list(head):
"""
Algorithm:
1. Find middle → split into two halves
2. Reverse second half
3. Merge the two halves alternately
Time: O(n), Space: O(1)
"""
if not head or not head.next:
return
# Step 1: Find middle
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# Step 2: Reverse second half
second = slow.next
slow.next = None # Split
prev = None
while second:
next_node = second.next
second.next = prev
prev = second
second = next_node
second = prev # Head of reversed second half
# Step 3: Merge alternately
first = head
while second:
tmp1 = first.next
tmp2 = second.next
first.next = second
second.next = tmp1
first = tmp1
second = tmp2Problem 5 — Rotate List by K Positions
Problem: Rotate the list to the right by k places.
def rotate_right(head, k):
"""
1. Find length and tail
2. k = k % length (handle large k)
3. New tail is at position (length - k - 1) from start
4. Break the list and re-link
Time: O(n), Space: O(1)
"""
if not head or not head.next or k == 0:
return head
# Step 1: Find length and tail
tail = head
length = 1
while tail.next:
tail = tail.next
length += 1
# Step 2: Normalize k
k = k % length
if k == 0:
return head
# Step 3: Find new tail (length - k - 1 steps from head)
new_tail = head
for _ in range(length - k - 1):
new_tail = new_tail.next
# Step 4: Re-link
new_head = new_tail.next
new_tail.next = None
tail.next = head
return new_headProblem 6 — Odd-Even Linked List
Problem: Group all odd-indexed nodes first, then all even-indexed nodes. Maintain relative order. O(1) space.
def odd_even_list(head):
"""
Maintain two separate chains: odd-indexed and even-indexed.
Connect odd chain tail to even chain head.
Time: O(n), Space: O(1)
"""
if not head:
return head
odd = head
even = head.next
even_head = even # Save even head for reconnection
while even and even.next:
odd.next = even.next # Odd → next odd
odd = odd.next # Advance odd
even.next = odd.next # Even → next even
even = even.next # Advance even
odd.next = even_head # Connect odd tail to even head
return headProblem 7 — Merge K Sorted Lists
Problem: Merge k sorted linked lists into one sorted list.
import heapq
def merge_k_lists(lists):
"""
Min-heap approach: maintain a heap of the current minimum across all lists.
Time: O(n log k), Space: O(k)
where n = total nodes, k = number of lists
"""
heap = [] # (value, list_index, node)
# Initialize heap with the head of each list
for i, node in enumerate(lists):
if node:
heapq.heappush(heap, (node.data, i, node))
dummy = Node(0)
current = dummy
while heap:
val, i, node = heapq.heappop(heap)
current.next = node
current = current.next
if node.next:
heapq.heappush(heap, (node.next.data, i, node.next))
return dummy.nextDivide and conquer approach — O(n log k), O(log k) space:
Problem 8 — Flatten a Multilevel Doubly Linked List
Problem: A doubly linked list where nodes can have a child pointer to another doubly linked list. Flatten it so all nodes are in a single level.
def flatten(head):
"""
When we encounter a node with a child, insert the child list inline.
Time: O(n), Space: O(1)
"""
if not head:
return head
current = head
while current:
if current.child:
child = current.child
next_node = current.next
# Connect current → child
current.next = child
child.prev = current
current.child = None
# Find tail of child list
tail = child
while tail.next:
tail = tail.next
# Connect child tail → next_node
tail.next = next_node
if next_node:
next_node.prev = tail
current = current.next
return headProblem 9 — Sort List (O(n log n), O(1) Space)
def sort_list(head):
"""
Merge sort on linked list.
Time: O(n log n), Space: O(log n) for recursion.
"""
if not head or not head.next:
return head
# Find middle and split
mid = find_middle_for_sort(head)
right = mid.next
mid.next = None
left = sort_list(head)
right = sort_list(right)
return merge_sorted(left, right)
def find_middle_for_sort(head):
"""Returns the node just before the middle (for clean splitting)."""
slow = head
fast = head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slowProblem 10 — Linked List Cycle II (Find Cycle Start)
def detect_cycle(head):
"""
Return the node where the cycle begins, or None.
Floyd's two-phase algorithm.
Time: O(n), Space: O(1)
"""
slow = fast = head
# Phase 1: Detect meeting point
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
break
else:
return None # No cycle
# Phase 2: Find cycle start
# Mathematical proof: distance from head to cycle start
# equals distance from meeting point to cycle start
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow # Cycle startProblem 11 — Swap Nodes in Pairs
Problem: Swap every two adjacent nodes. Do not change values, only links.
def swap_pairs(head):
"""
Iterative: use dummy head and prev pointer to swap pairs.
Time: O(n), Space: O(1)
"""
dummy = Node(0)
dummy.next = head
prev = dummy
while prev.next and prev.next.next:
first = prev.next
second = prev.next.next
# Swap
prev.next = second
first.next = second.next
second.next = first
# Advance
prev = first
return dummy.nextProblem 12 — Maximum Twin Sum
Problem: In a linked list of even length n, the twin of node i is node (n-1-i). Find the maximum twin sum.
def pair_sum(head):
"""
Find middle → reverse second half → add corresponding nodes.
Time: O(n), Space: O(1)
"""
# Find middle
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# Reverse second half
prev = None
current = slow
while current:
next_node = current.next
current.next = prev
prev = current
current = next_node
# Compare first half with reversed second half
max_sum = 0
left = head
right = prev
while right:
max_sum = max(max_sum, left.data + right.data)
left = left.next
right = right.next
return max_sumPattern Summary
| Problem | Pattern | Time | Space |
|---|---|---|---|
| Remove nth from end | Two pointers, gap n | O(n) | O(1) |
| Add two numbers | Digit-by-digit simulation | O(max(m,n)) | O(n) |
| Copy with random pointer | Hash map or weaving | O(n) | O(n)/O(1) |
| Reorder list | Split + reverse + merge | O(n) | O(1) |
| Rotate list | Find tail + re-link | O(n) | O(1) |
| Odd-even list | Two chains | O(n) | O(1) |
| Merge k sorted | Min-heap | O(n log k) | O(k) |
| Flatten multilevel | Inline insertion | O(n) | O(1) |
| Sort list | Merge sort | O(n log n) | O(log n) |
| Cycle detection II | Floyd's two-phase | O(n) | O(1) |
| Swap pairs | Dummy + iterative | O(n) | O(1) |
| Maximum twin sum | Split + reverse | O(n) | O(1) |
Summary
The linked list section covers the complete spectrum:
- Foundation: Node structure, types, memory model
- Operations: Insert, delete, search, traverse for all three types
- Core techniques: Two-pointer (slow-fast), dummy head, reversal
- Classic problems: The 12 problems above cover every important pattern
The two-pointer technique and the three-pointer reversal are the backbone. Everything else is a variation or combination of these fundamental patterns.
*Linked Lists section complete. Next: Stacks — Introduction*
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Linked List Interview Problems — 12 Classic Problems with Complete Solutions.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Data Structures & Algorithms topic.
Search Terms
data-structures-algorithms, data structures & algorithms, data, structures, algorithms, linked, lists, list
Related Data Structures & Algorithms Topics