Linked Lists · Linked List Fundamentals

Linked List Flattening

Merging many independently-sorted linked lists into one sorted list by folding them together two at a time with the ordinary sorted-merge routine.

  • 5 min read
  • 11 practice questions
  • 2 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: splicing in place, not merging by value
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

Flattening turns a linked structure with two or more levels into one list. Two different problems share the name. One merges sorted sub-lists that hang off a top-level chain into one sorted list, a k-way merge. The other unfolds a multilevel doubly linked list so each child list appears right after its parent node, a depth-first walk that splices in place. Knowing which one you face decides the whole approach.

We'll go from simple to more technical:

  1. The pattern: fold sorted sub-lists together with the two-list merge.
  2. A second flavor: splice child lists in place, in depth-first order.
  3. Where each kind of flattening shows up in production.
  4. The pointer bugs: lost continuations and half-updated prev links.

The approach

In the first problem, each top-level node starts a sorted sub-list that runs along its child pointer. The top-level nodes are linked by next. You already know how to merge two sorted lists. So walk the top level and merge each sub-list into a growing result, one at a time. The only twist is that the sorted order follows child instead of next.

Three sub-lists hang off the top level: 3 9 15, 6 7 and 1 12.

StepSub-list merged inResult so far (along child)
13 9 153 9 15
26 73 6 7 9 15
31 121 3 6 7 9 12 15

The top level doesn't need to be in order: the sub-list starting at 1 comes last and still lands first.

Java

Node flatten(Node head) {
    Node result = null;
    Node cur = head;
    while (cur != null) {
        Node nextTop = cur.next;      // remember before merging disturbs pointers
        result = mergeByChild(result, cur);
        cur = nextTop;
    }
    return result;
}
// mergeByChild is exactly linked-list-merge-technique's merge, just walking
// .child instead of .next

Python

def flatten(head: Node | None) -> Node | None:
    result = None
    cur = head
    while cur is not None:
        next_top = cur.next          # remember before merging disturbs pointers
        result = merge_by_child(result, cur)
        cur = next_top
    return result
# merge_by_child is exactly linked-list-merge-technique's merge, just walking
# .child instead of .next

Save cur.next before merging. The merge rewires the nodes of cur's sub-list, and afterwards cur's own pointers may no longer lead where they did.

A second flavor: splicing in place, not merging by value

The second problem has nothing sorted in it. In a multilevel doubly linked list, any node may have a child chain, and that chain belongs right after the node. Children can have children too. The final order comes from position, not from comparing values. Walk the list. When a node has a child, push the node that used to follow it onto a stack, splice the child in, and keep walking. When a chain runs out, pop the stack and continue from there.

Say 1 <-> 2 <-> 3, where 2 has the child chain 5 <-> 6, and 5 has its own child 9. It flattens to 1, 2, 5, 9, 6, 3.

Java

Node flatten(Node head) {
    Node curr = head;
    Deque<Node> stack = new ArrayDeque<>();
    while (curr != null) {
        if (curr.child != null) {
            if (curr.next != null) stack.push(curr.next);   // remember where to resume
            curr.next = curr.child;
            curr.next.prev = curr;                            // update BOTH directions at the seam
            curr.child = null;
        }
        if (curr.next == null && !stack.isEmpty()) {
            curr.next = stack.pop();
            curr.next.prev = curr;                            // same: both directions
        }
        curr = curr.next;
    }
    return head;
}

Python

def flatten(head: Node | None) -> Node | None:
    curr = head
    stack = []
    while curr is not None:
        if curr.child is not None:
            if curr.next is not None:
                stack.append(curr.next)      # remember where to resume
            curr.next = curr.child
            curr.next.prev = curr            # update BOTH directions at the seam
            curr.child = None
        if curr.next is None and stack:
            curr.next = stack.pop()
            curr.next.prev = curr            # same: both directions
        curr = curr.next
    return head

Each splice joins two nodes. The list is doubly linked, so both links at the seam need updating: next going forward and prev coming back.

Where you'll see it

The first kind is a k-way merge: several sorted sources, such as search-index segments or sorted pages of API results, become one ranked stream. Folding them in one at a time is fine for a few. For many, pair them up or use a min-heap (see the Merge Technique skill). The second kind turns a nested document outline or a multi-level task list into one reading order. There, order comes from the structure, never from comparing values.

Which tool for which job?

You needUse
One sorted list from sorted sub-lists, a few of themfold them in with the two-list merge
The same, many sub-listspair them up, or a min-heap - O(N log k)
Children placed right after their parentdepth-first: splice each child list in place
The same, O(1) extra spacefind each child's tail and splice, no stack
Very deep nestingan explicit stack, not recursion
Confidence in a doubly linked resultcheck node.next.prev is node everywhere

Common mistakes

MistakeWhat happensDo this instead
Reading cur.next after merging curwalks into the merged structuresave the continuation first
Setting only next at a splicebackward traversal is brokenset prev on both sides
Leaving child pointers seta node still looks multilevelclear child after splicing
Recursing per nesting levelstack overflow on deep nestingan explicit stack
Merging when the problem wants DFS order (or the reverse)the wrong orderread which "flatten" is asked

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Why save cur.next before merging the current sub-list?

Show answer

The merge reuses and rewires that sub-list's nodes. When it returns, cur's pointers may no longer lead to the next top-level node. Saving cur.next first keeps the loop on track.

2. Must the top-level nodes be sorted by their first values?

Show answer

No. Only each sub-list must be sorted. The merge does the ordering, so a sub-list merged in late still lands in the right place, as the one starting at 1 did above.

3. A flattened multilevel list reads correctly forwards but wrongly backwards. What's the likely cause?

Show answer

A splice set next but not prev. Walking forwards only follows next, so it never notices. Walking backwards follows the stale prev into the wrong place. Every seam needs both links updated.

Key takeaways

  • Flattening sorted sub-lists reuses the two-list merge, one sub-list at a time.
  • Save the next top-level node before the merge rewires the current one.
  • Only the sub-lists must be sorted, not the top level.
  • A multilevel doubly linked list has nothing to sort. Splice each child in where it hangs, and use a stack to remember where to resume.
  • At every seam in a doubly linked list, update both next and prev.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
Sorted sub-lists → one sorted listmerge (pair up / heap for many)
Children after their parentpreorder DFS
O(1) space DFSsplice each child's tail
Deep nestingan explicit stack
Doubly linked confidenceassert next.prev == node

Snippets worth knowing by heart

Java

for (Node cur = head; cur != null; cur = cur.next) {
    if (cur.child == null) continue;
    Node tail = cur.child;
    while (tail.next != null) tail = tail.next;
    tail.next = cur.next;
    if (cur.next != null) cur.next.prev = tail;   // both directions
    cur.next = cur.child;
    cur.child.prev = cur;
    cur.child = null;
}

Python

node = head
while node and node.next:
    assert node.next.prev is node, (node.val, node.next.val)   # catches a missing prev
    node = node.next

The traps

  • Losing cur.next: after merging you walk into the merged structure. Save the continuation first.
  • Only next updated: backward traversal breaks. Set prev on both sides of a splice.
  • Leftover child pointers: a node still looks multilevel. Clear child after splicing.
  • Deep recursion: deep nesting overflows the stack. Use an explicit stack.
  • The wrong kind of flatten: merging when DFS order is wanted, or the reverse. Read which one is asked.

Staff-level points, one line each

  • Multilevel flatten = preorder DFS.
  • Splicing tails: O(1) space, at most 1.66 visits per node on 300 random lists.
  • 3,000 nested levels: recursion raised RecursionError; a stack flattened all 3,000.
  • Missing prev: forward 1 3 2 looked right; backward was 2 3.
  • Sorted flatten: fold O(N k), pair up / heap O(N log k).

Say it in an interview

  • "Children come right after their parent, so this is a preorder walk."
  • "I splice each child list in where it hangs, updating prev and next on both sides."
  • "I'd use a stack rather than recursion in case the nesting is deep."
  • "I check both directions in tests."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals and 2 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Linked List Flattening free

Flattening of a LinkedList

HardProCoding problemJava · Python

You are given m linked lists, each already sorted ascending. The i-th top-level node is the head of its own sorted sub-list, connected via a child pointer; the top-level nodes themselves are connected via next.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Flatten a Multilevel Doubly Linked List

HardProCoding problemJava · Python

You are given the head of a doubly linked list where, in addition to next and prev, each node may have a child pointer to a separate doubly linked list, which should be inserted immediately after that node in the flattened result.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Linked List Flattening free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime