You are given a doubly linked list, which contains nodes that have a next pointer, a previous pointer, and an additional child pointer. This child pointer may or may not point to a separate doubly linked list, also containing these special nodes. These child lists may have one or more children of their own, and so on, to produce a multilevel data structure as shown in the example below.
Given the head of the first level of the list, flatten the list so that all the nodes appear in a single-level, doubly linked list. Let curr be a node with a child list. The nodes in the child list should appear after curr and before curr.next in the flattened list.

solution
class Solution:
def flatten(self, head: 'Optional[Node]') -> 'Optional[Node]':
def recurse(node):
if not node:
return None
# base case, nowhere to recurse so just return the node
elif not node.next and not node.child:
return node
else:
n = node.next
# we'll return when we reach a basecase node, so that'll be the
# tail that we connect between our current node and the next node
if node.child:
tail = recurse(node.child)
node.next = node.child
node.child.prev = node
node.child = None
tail.next = n
if n:
n.prev = tail
else:
# we want to return tail instead of recursing on node.next
# if node.next is None (if we're at the end of the level)
# (similar idea to the above elif case, because
# tail is guaranteed to have no next or child)
# tail is the end of the flattened list that
# was processed in the recursive call
return tail
*return* recurse(n)
recurse(head)
return head