leetcode-430-扁平化多级双向链表
- 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
[博客链接]
[题目链接]
[github地址]
[题目描述]
多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
给你位于列表第一级的头节点,请你扁平化列表,使所有结点出现在单级双链表中。
示例 1:
输入:head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12] 输出:[1,2,3,7,8,11,12,9,10,4,5,6]
示例 2:
输入:head = [1,2,null,3] 输出:[1,3,2] 解释:
输入的多级列表如下图所示:
1---2---NULL | 3---NULL 示例 3:
输入:head = [] 输出:[]
如何表示测试用例中的多级链表?
以 示例 1 为例:
1---2---3---4---5---6--NULL | 7---8---9---10--NULL | 11--12--NULL 序列化其中的每一级之后:
- [1,2,3,4,5,6,null]
- [7,8,9,10,null]
- [11,12,null]
为了将每一级都序列化到一起,我们需要每一级中添加值为 null 的元素,以表示没有节点连接到上一级的上级节点。
-
[1,2,3,4,5,6,null]
-
[null,null,7,8,9,10,null]
-
[null,11,12,null] 合并所有序列化结果,并去除末尾的 null 。
-
[1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]
提示:
- 节点数目不超过 1000
- 1 <= Node.val <= 10^5
思路一:递归解法
- 如果head为空直接返回即可
- 否则每次遍历所有子节点,记录当前节点,然后拼接后跨越下个节点
- 注意前后指针的赋值关系
public Node flatten(Node head) {
//corner case
if (head == null){
return head;
}
Node dummy = new Node(0,null,head,null);
dfs(dummy,head);
dummy.next.prev = null;
return dummy.next;
}
public Node dfs(Node pre, Node cur) {
if (cur == null){
return pre;
}
pre.next = cur;
Node temp = cur.next;
cur.prev = pre;
Node tail = dfs(cur,cur.child);
cur.child = null;
return dfs(tail ,temp);
}
- 时间复杂度O(n)
- 空间复杂度O(1)
思路二:非递归解法
- 定义一个栈存储节点
- 先放入同级后续节点
- 后放入子节点
- 然后反向弹出拼接即可
public Node flatten(Node head) {
if (head == null){
return head;
}
Node dummy = new Node(0,null,head,null);
Node pre = dummy;
Node cur = head;
Stack<Node> stack = new Stack<>();
stack.push(head);
while (!stack.isEmpty()){
cur = stack.pop();
pre.next = cur;
cur.prev = pre;
if (cur.next != null){
stack.push(cur.next);
}
if (cur.child != null) {
stack.push(cur.child);
// don't forget to remove all child pointers.
cur.child = null;
}
pre = cur;
}
dummy.next.prev = null;
return dummy.next;
}
- 时间复杂度O(n)
- 空间复杂度O(n)