题目描述
多级双向链表中,除了指向下一个节点和前一个接待你指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子链表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
给你位于列表第一级的头节点,请你扁平化列表,使所有节点出现在单极双链表中。
示例1:
输入: head = [1, 2, 3, 4, 5, 6, null, null, null, 7, 8, 9, 10, null, null, 11, 12]
输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
解释:
** 图1**
示例2:
输入: head = []
输出: []
说明:
- 节点数目不超过1000
1 <= node.val < 10E5
思路分析
我们看到题干首先想到的是,深度优先搜索算法,所以我们直接借助栈stack
保存具有child
非空指针后的节点,当深度遍历完之后,从stack
中弹出保存点,接着遍历。
图2
我们通过图2可知,设遍历指针为curr
,红色箭头为curr
的遍历轨迹:
- 当存在
child
节点时,将curr.next
压入栈中,直接遍历curr.child
; - 当在下沉过程中,又检测到
child
节点,则重复步骤1; - 在最后一级链表到尽头时,检测栈是否为空:不为空则弹出栈顶元素(返回上一级链表);为空则完成多级链表的遍历,直接输出结果
output
.
解题步骤
- 初始化两个分区指针
oddTail, evenTail
和布尔变量isOddNode
; - 遍历原始链表,根据
isOddNode
判断evenTail.next
是否插入奇数分区; - 当
evenTail.next == null
时停止并返回head
.
解题代码
public static ListNode solution(ListNode head) {
if (head == null) {
return head;
}
/* Step1: Init. pointers */
Stack<ListNode> stack = new Stack<>();
ListNode curr = head;
/* Step2: go through the head-list
and
go back last level when no more subsequent child and next nodes
*/
while (curr != null) {
// exists child-node
if (curr.child != null) {
ListNode node = curr.next;
stack.push(node);
curr.next = curr.child;
}
// back to last level
if (curr.next == null && !stack.isEmpty()) {
curr.next = stack.peek();
curr = stack.pop();
}
curr = curr == null ? null : curr.next;
}
/* Step3: return head */
return head;
}
复杂度分析
时间复杂度:我们对原始链表进行了一次遍历,容易理解时间复杂度为O(N)
;
空间复杂度:我们这里设置了辅助容器stack
,故空间复杂度为O(N)
.
GitHub源码
完整可运行文件请访问GitHub。