[LeetCode] 430. Flatten a Multilevel Doubly Linked List

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.

Return the head of the flattened list. The nodes in the list must have all of their child pointers set to null.

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

How the multilevel linked list is represented in test cases:

We use the multilevel linked list from Example 1 above:

 1---2---3---4---5---6--NULL
         |
         7---8---9---10--NULL
             |
             11--12--NULL

The serialization of each level is as follows:

[1,2,3,4,5,6,null]
[7,8,9,10,null]
[11,12,null]

To serialize all levels together, we will add nulls in each level to signify no node connects to the upper node of the previous level. The serialization becomes:

[1,    2,    3, 4, 5, 6, null]
             |
[null, null, 7,    8, 9, 10, null]
                   |
[            null, 11, 12, null]

Merging the serialization of each level and removing trailing nulls we obtain:

[1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]

扁平化多级双向链表。

你会得到一个双链表,其中包含的节点有一个下一个指针、一个前一个指针和一个额外的 子指针 。这个子指针可能指向一个单独的双向链表,也包含这些特殊的节点。这些子列表可以有一个或多个自己的子列表,以此类推,以生成如下面的示例所示的 多层数据结构 。

给定链表的头节点 head ,将链表 扁平化 ,以便所有节点都出现在单层双链表中。让 curr 是一个带有子列表的节点。子列表中的节点应该出现在扁平化列表中的 curr 之后 和 curr.next 之前 。

返回 扁平列表的 head 。列表中的节点必须将其 所有 子指针设置为 null 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/flatten-a-multilevel-doubly-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目即是题意,请你将这个多维的链表转化成一个一维的链表。

思路还是像遍历一般链表一样去遍历,当遇到 child node 的时候,看一下当前节点是否有 next node,若有,需要用 stack 存下来,然后将当前 node 的 next 指针指向 child,也将 child 的 prev 指针指向 cur,最后记得将当前节点的child指针置为null。这样起码可以把多维的链表先变成一维的。此时此刻应该是会遍历到链表的尾部了,此时看一下 stack 是否为空,如果不为空,开始往外弹出节点,接到 cur 后面,同时记得将 cur 后边这个节点的 prev 指针再指向 cur,这样才叫双向链表。

时间O(n)

空间O(n) - stack

Java实现

 1 /*
 2 // Definition for a Node.
 3 class Node {
 4     public int val;
 5     public Node prev;
 6     public Node next;
 7     public Node child;
 8 };
 9 */
10 
11 class Solution {
12     public Node flatten(Node head) {
13         // corner case
14         if (head == null) {
15             return head;
16         }
17         Deque<Node> stack = new ArrayDeque<>();
18         Node cur = head;
19         while (cur != null) {
20             if (cur.child != null) {
21                 if (cur.next != null) {
22                     stack.push(cur.next);
23                 }
24                 cur.next = cur.child;
25                 if (cur.next != null) {
26                     cur.next.prev = cur;
27                 }
28                 cur.child = null;
29             } else if (cur.next == null && !stack.isEmpty()) {
30                 cur.next = stack.pop();
31                 if (cur.next != null) {
32                     cur.next.prev = cur;
33                 }
34             }
35             cur = cur.next;
36         }
37         return head;
38     }
39 }

 

二刷我参考了discussion的最高票答案,无需额外空间。

我照着例子一这个图讲一下。从 1 开始往后走 1,2,3,走到 3 的时候发现这个 node 是有 child 指针的(7),此时我们记录一下 3 之后的节点 4,这是为了以防丢失节点 4,并把 3 - > 4 断开。

此时我们从 7 一路遍历到 10,然后把 10 跟 4 的 next 和 prev 指针处理一下,这样 10 和 4 能互相找到。整体上看,是为了把下一层的 node 放到 3 和 4 中间。

此时从 3 走到 7,再走到 8,此时又发现有 child node,那么做法一样,把 11 - 12 这一段放到 8 和 9 中间即可。

时间O(n)

空间O(1)

Java实现

 1 /*
 2 // Definition for a Node.
 3 class Node {
 4     public int val;
 5     public Node prev;
 6     public Node next;
 7     public Node child;
 8 };
 9 */
10 
11 class Solution {
12     public Node flatten(Node head) {
13         // corner case
14         if (head == null) {
15             return head;
16         }
17 
18         // normal case
19         Node cur = head;
20         while (cur != null) {
21             // 会一直走到3
22             if (cur.child == null) {
23                 cur = cur.next;
24                 continue;
25             }
26             // 此时3是有child node的
27             // temp = 7
28             Node temp = cur.child;
29             // 从7一直走到10
30             while (temp.next != null) {
31                 temp = temp.next;
32             }
33             // 10 -> 4
34             temp.next = cur.next;
35             // 10 <=> 4,完成双向链表
36             if (cur.next != null) {
37                 cur.next.prev = temp;
38             }
39             // 3 -> 7
40             cur.next = cur.child;
41             // 3 <- 7
42             cur.child.prev = cur;
43             // 把child指针置为NULL
44             cur.child = null;
45         }
46         return head;
47     }
48 }

 

相关题目

114. Flatten Binary Tree to Linked List

430. Flatten a Multilevel Doubly Linked List

897. Increasing Order Search Tree

LeetCode 题目总结

posted @ 2020-07-11 01:58  CNoodle  阅读(196)  评论(0编辑  收藏  举报