你会得到一个双链表,其中包含的节点有一个下一个指针、一个前一个指针和一个额外的 子指针 。这个子指针可能指向一个单独的双向链表,也包含这些特殊的节点。这些子列表可以有一个或多个自己的子列表,以此类推,以生成如下面的示例所示的 多层数据结构 。
给定链表的头节点 head ,将链表 扁平化 ,以便所有节点都出现在单层双链表中。让 curr 是一个带有子列表的节点。子列表中的节点应该出现在扁平化列表中的 curr 之后 和 curr.next 之前 。
返回 扁平列表的 head 。列表中的节点必须将其 所有 子指针设置为 null 。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/flatten-a-multilevel-doubly-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
读题的时候看题目的示意图,发现只要有子结点的结点node,它的子链表就会放在它自身和node.next之间。因此我们可以这样想:当我们向后遍历链表的时候,如果发现了结点node有子链表node.child,就先把node.next给它放在temp里面存起来,然后来处理子链表,把node.next指向扁平化后的子链表;处理完子链表,就要将temp重新放到原链表的结尾,所以要设置一个指针remain,它要继续向后遍历到下一个结点为空,循环条件为remain.next!=null ,之后将remain.next = temp,然后继续往下处理。
思路整理完毕,我们就可以开始写代码了。
但这题最恶心的地方在于你可能输出的答案是对的,但是新的链表已经是无效的双链表了,意味着你的某些结点的prev指向null或者其他地方。所以在每一次处理子链表的时候,要记得将子链表的prev指向它的父链表,将node.next.prev指向该指向的地方;
public static Node flatten(Node head) { if(head == null ){ return null; } if(head.next==null){ Node next = flatten(head.child); head.next = next; if(next!=null){ //把双向链表完善 next.prev = head; } return head; } Node cur = head; while(cur!=null){ if(cur.child!=null){ Node temp = cur.next; //完善双向链表 cur.child.prev=cur; cur.next=cur.child; Node remain = cur.child; while(remain.next!=null){ remain = remain.next; } //递归处理子链表 Node next = flatten(temp); if(next!=null){ //完善双向链表 next.prev = remain; } remain.next = next; } cur.child = null; cur = cur.next; } return head; }