力扣430(java)-扁平化多级双向链表(中等)

题目:

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

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

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

示例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] 解释:输入的多级列表如上图所示。 扁平化后的链表如下图:

  

示例3:

输入:head = [] 输出:[] 说明:输入中可能存在空列表。

 提示:

  • 节点数目不超过 1000
  • 1 <= Node.val <= 105

解题思路:

深度优先搜索(DFS)

当遍历到某个结点时,如果它的孩子成员不为空,那么就需要将孩子结点指向的链表进行扁平化,然后插入到当前结点与该结点的下一个结点之间。

具体做法:

  1. 首先判断当前结点这条链是否为空,为空就直接返回;
  2. 如果当前结点的孩子结点不为空:
    • 记录当前结点的下一个结点;
    • 对子链表进行dfs遍历;
    • 对所有的子链表进行扁平化后,再扁平化当前层的链表,将当前结点的下一个结点作为当前结点的孩子结点,并进行反向绑定;
    • 寻找当前层的扁平化后链表的最后一个结点,将尾结点与原来当前结点的下一个结点进行连接
    • 然后将子链表置空;
    • 继续从上一个next开始遍历

       3.如果当前结点的孩子结点为空,继续遍历当前结点的下一个结点。

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         //遍历每一个结点
14         dfs(head);
15         return head;
16     }
17     private void dfs(Node node){
18         //当node为空时就退出当前遍历
19         if(node == null) return;
20         //如果子节点不为空
21         if(node.child != null){
22             //记录当前node的下一个结点
23             Node next = node.next;
24             //遍历子链表
25             dfs(node.child);
26 
27             //将当前结点的下一个结点变为该节点的孩子结点
28             node.next = node.child;
29             //反向绑定,子链表的上一个节点为当前结点
30             node.child.prev  = node;
31 
32             //寻找子链表的尾结点
33             Node tail = node.child;
34             while(tail.next != null){
35                 tail = tail.next;
36             }
37 
38             //把链表的尾与原来当前结点的下一个结点连接
39             //判断一下是否为空
40             if(next != null){
41                 next.prev = tail;
42             }
43             //反向绑定,将尾巴的下一个结点指向next
44             tail.next = next;
45 
46             //将子链表置空
47             node.child = null;
48 
49             //从上一个next开始继续遍历
50             dfs(next);
51         }else{
52             //如果子节点为空
53             dfs(node.next);         
54         }
55     }   
56 }

感悟:

今天这题画图挺好理解的,就是看代码很绕,又是怀疑自己的一天....

posted on 2022-09-15 16:15  我不想一直当菜鸟  阅读(40)  评论(0编辑  收藏  举报