Last Updated: April 1, 2026
At first glance, this looks like a tree-to-list conversion problem, and that intuition is spot on. The multilevel structure is essentially a tree where each node can have both a "next sibling" (the next pointer) and a "first child" (the child pointer). Our job is to splice every child chain into the main list, right after the parent node.
The tricky part is handling nested children. A child list can itself have children, forming arbitrarily deep nesting. So whatever approach we use needs to handle recursion or repeated traversal until every child pointer has been flattened away.
Here is the key observation: when we encounter a node with a child, we need to insert the entire child chain between that node and its next node. After insertion, the child pointer should be set to null. If the child chain itself has children, those will be encountered and flattened as we continue traversing the now-merged list.
Number of nodes <= 1000 → With n up to 1000, even O(n^2) is under a million operations. But O(n) is clearly achievable and preferred.1 <= Node.val <= 10^5 → Values are positive integers. Not particularly relevant to the algorithm, but confirms no special sentinel values.prev, next, and child pointers correctly. Forgetting to null out the child pointer or update prev pointers are common bugs.The multilevel structure is really a tree disguised as linked lists. The next pointer is like a right sibling, and the child pointer is like a left child. Flattening means doing a pre-order DFS traversal and linking all visited nodes into a single doubly linked list.
A stack-based DFS gives us explicit control over the traversal order. When we encounter a node, we push its next onto the stack (to revisit later) and then push its child (to visit immediately). Since a stack is LIFO, pushing next first and child second ensures we process the child before the next sibling, which is exactly the order we want.
prev node to simplify pointer management.prev (set prev.next = curr, curr.prev = prev).next, push next onto the stack.child, push child onto the stack, then set the node's child to null.prev = curr.head.prev = null.The stack uses O(n) extra space to track nodes. But the next pointers already exist in the list itself. What if we walked to the tail of each child chain and stitched it directly to the next node?
Instead of using a stack, we can flatten the list in-place by iterating through it. When we find a node with a child, we do three things: find the tail of the child chain, connect the tail to the node's next, and connect the node to the child. Then we null out the child pointer and keep walking forward.
The iterative approach works because flattening is a local operation. When we splice a child chain into the main list, the tail of the child chain connects to whatever used to come after the parent node, preserving traversal order.
The key insight about time complexity: finding the tail of a child chain takes O(k) where k is the length of that child chain. But each node can only be part of one tail search, because once a child chain is spliced in, those nodes become part of the main list and are never searched again. So the total work across all tail searches is O(n), not O(n^2).
curr at the head.curr is not null:curr has a child: a. Save curr.next as next.
b. Walk to the tail of the child chain.
c. Connect curr.next = curr.child and curr.child.prev = curr.
d. Connect tail.next = next and (if next is not null) next.prev = tail.
e. Set curr.child = null.
curr = curr.next.curr, next, tail). No stack or recursion needed.