
Problem Statement
In this problem, you are provided with a unique data structure - a doubly linked list extended with a child pointer that may point to another doubly linked list. These chained lists can create deep hierarchies or multilevel structures. Your task is to flatten this multilevel doubly linked list so that all nodes are in a single, linear doubly linked list. Specifically, if a node named curr
has a child list, the entire child list should be unpacked and inserted between curr
and curr.next
. In the end, you should return the head of the flattened list, all child pointers set to null
indicate that the list has been correctly flattened.
Examples
Example 1
Input:
head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]
Output:
[1,2,3,7,8,11,12,9,10,4,5,6]
Explanation:
The multilevel linked list in the input is shown. After flattening the multilevel linked list it becomes:
Example 2
Input:
head = [1,2,null,3]
Output:
[1,3,2]
Explanation:
The multilevel linked list in the input is shown. After flattening the multilevel linked list it becomes:
Example 3
Input:
head = []
Output:
[]
Explanation:
There could be empty list in the input.
Constraints
- The number of Nodes will not exceed
1000
. 1 <= Node.val <= 105
Approach and Intuition
The key to solving the flattening of a multilevel doubly linked list lies in correctly and systematically processing the child
pointers and integrating those child lists into the main list.
Tracking Nodes: Start from the head of the list and iterate through each node. For each node encountered, check if there is a child node associated with it.
Processing Child Nodes:
- If a
child
is found, detach this sublist from the main list by setting thechild
pointer tonull
for the current node. - Integrate this child list into the main list. The integration is done at the place right after the current node and before the
next
node of the current node.
- If a
Managing Integration Seamlessly:
- To do this integration, you would need to get to the end of the child list, connect the last node of this child list to
curr.next
, and also update theprevious
pointer of thecurr.next
(if it exists) to the last node of the child list. - Continue the iteration but now integrate the lists one node at a time, and each sublist similarly upon encountering a new child list recursively.
- To do this integration, you would need to get to the end of the child list, connect the last node of this child list to
Ensuring Continuous Integration: As you continue through each node, make sure to check for further child lists even within newly integrated nodes since it can be a recursively defined structure.
By recursively and iteratively integrating child lists directly into the main list as soon as they are encountered, this approach ensures that all nodes are processed and the list is flattened sequentially. This method is robust because it deals dynamically with varying list depths and complex child-to-child connections without losing track of the main list's flow.
Solutions
- Java
class Solution {
public Node flatten(Node head) {
if (head == null) return null;
Node tempHead = new Node(0, null, head, null);
Node current, previous = tempHead;
Deque<Node> nodesStack = new ArrayDeque<>();
nodesStack.push(head);
while (!nodesStack.isEmpty()) {
current = nodesStack.pop();
previous.next = current;
current.prev = previous;
if (current.next != null) nodesStack.push(current.next);
if (current.child != null) {
nodesStack.push(current.child);
current.child = null;
}
previous = current;
}
tempHead.next.prev = null;
return tempHead.next;
}
}
The provided Java code addresses the problem of flattening a multilevel doubly linked list. Each node in the list has a child pointer, which may point to another doubly linked list. This intricacy forms a "multilevel" linked list, where some nodes can have one or several levels of children lists nested inside the main list.
Here is an explanation of how the given code solves this problem:
Initialization:
- Creates a
tempHead
node to act as a starting point to ease the handling of edge cases where the original head might change. - Initializes a stack
nodesStack
to manage the nodes yet to be processed. - The main list head node is initially pushed into
nodesStack
.
- Creates a
Processing Nodes:
- The algorithm proceeds with a while loop that continues until all nodes are processed (i.e., until the stack is empty).
- In each iteration, the top node of the stack is popped and processed:
- Updates the backward link using
previous
to maintain the doubly linked nature. - If a node has a
next
node, it pushes it into the stack for later processing. - Importantly, if a node has a child, it pushes the child to the stack and breaks the link by setting the child to null.
- The
previous
pointer is updated to the current node after the links are adjusted.
- Updates the backward link using
Cleanup and Completion:
- Once all nodes are processed, the artificial
tempHead's
next node's previous link is set to null to properly format the flattened list. - Finally, the function returns the flattened linked list from
tempHead.next
, effectively skipping the artificial head.
- Once all nodes are processed, the artificial
This code effectively flattens the list in-place, ensuring that all levels of child nodes are integrated into the primary level, removing any child links, and maintaining the backward and forward links typical of a doubly linked list.
No comments yet.