概述
114. 二叉树展开为链表
430. 扁平化多级双向链表
114 这道题目要求我们把一颗二叉树展开成链表
430 这道题目要求我们把复杂的链表展开
114题解已经发布在这篇博客,这里不再赘述了
下面写430的题解
先序递归
仔细观察这个链表结构,发现我们按照先序递归的方式来访问这个复杂链表,刚好就能得到展开后的结果,那么可以写出代码:
class Solution:
def flatten(self, head: 'Node') -> 'Node':
if not head:
return head
self.ans = Node(None,None,None,None)
self.cur = self.ans
self.helper(head)
# 处理头结点的指针,按要求返回
newhead = self.ans.next
newhead.prev = None
return newhead
def helper(self, head):
if not head:
return
# 按照cur,child,next的顺序遍历结点
# 处理next指针,必须先保存然后递归,不然会在结束子链表展开时进入循环
next = head.next
# 处理当前指针
self.cur.next = head
head.prev = self.cur
# 处理孩子指针
child = head.child
head.child = None
# 更新当前结点
self.cur = head
# 访问child结点、next结点
self.helper(child)
self.helper(next)
上面的几个地方
首先我们用self.ans来作为临时头节点方便操作
然后self.cur用来指向每次递归遍历访问的结点
在递归中,我们要把next指针和child指针摘下来,然后处理self.cur和head的关系,再对刚刚保存的next和child进行调用
最后返回的时候,要把返回节点的前一个结点置空,这样才能通过样例
fancy递归
当然读者可能觉得上面的递归不够fancy,那么我们可以更改一下代码,让它看起来高端一点
由于接下来的递归很fancy,所以我把它叫做fancy递归
首先我们检查这个数据结构:prev、next、child三个指针
然后题目要求我们把多级链表展开成单级链表,我们检查一下链表顺序可以发现按照以下规则递归处理即可:
- 空结点 返回
- 处理当前节点
- 处理孩子链表
- 处理后继链表
关键是处理完孩子链表后,我们要把孩子链表拼接在后继结点前面
这也好办,只需要处理孩子链表的时候,同时返回孩子链表的首尾链表结点即可
又因为处理孩子、后继链表两个代码一致,所以我们可以复用一段处理的代码,这段代码的功能是:把一条多级链表展开,同时返回展开后的尾结点
那么可以写出代码
class Solution:
def flatten(self, head: 'Node') -> 'Node':
if not head:
return head
dh = Node(None,None,None,None)
cur = dh
self.helper(cur,head)
dh.next.prev = None
return dh.next
# 给定cur和head,展开以head为首的链表,并且返回展开后的尾指针
def helper(self,cur,head):
if not head:
return cur # 注意返回的是cur
cur.next = head
head.prev = cur
next = head.next
child = head.child
head.child = None
tail = self.helper(head,child)
return self.helper(tail,next)
上面的代码看着就很fancy,写起来也很fancy,特别是tail那一行,如果没经过思考是想不到怎么取到最后一个指针的(因为每次传入的都是head和head的下级(孩子或后继)指针,最后临界的时候,head一定是空,那么就会返回cur,而cur表示的就是前一个节点,从全局上来说就是最后一个结点)
需要注意的是最好先保存head的next和child再传入,不然会出现一些循环错误
迭代
有先序递归就有先序迭代,先序迭代一定会用到栈,我们复习一下用栈来怎么做二叉树的先序遍历:
- 弹出栈顶元素,直接访问
- 如果右孩子不为空,入栈
- 如果左孩子不为空,入栈
放到这里就是:
- 弹出栈顶元素,直接访问
- 如果后继节点不为空,入栈
- 如果孩子不为空,入栈
和普通的迭代有点不同的是这道题要处理一下指针关系
class Solution:
def flatten(self, head: 'Node') -> 'Node':
if not head:
return head
stack = [head]
dh = Node(None,None,None,None)
pre = dh
while stack:
node = stack.pop()
pre.next = node
node.prev = pre
pre = node
if node.next:
stack.append(node.next)
if node.child:
stack.append(node.child)
node.child = None
dh.next.prev = None
return dh.next
搞定