面试题36.二叉搜索树与双向链表
- 题目
- 解题思路
- 代码
题目
- 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
- 我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
- 特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
P.S. 完整题目来源于leetcode
解题思路
由题意知,需进行中序遍历得到顺序排列的循环双向链表。
需要注意的是,head是树的最左侧元素,即中序遍历回溯的第一个元素,需要从中序遍历中得到。同时需要pre
和cur
节点,在中序遍历结束时,cur
只想None
,而pre
指向末尾元素。中序遍历时,将pre
的右节点设为cur
,将cur
的左节点设为pre
,从而形成双向链表。在中序遍历结束,使得head
的左节点为pre
,pre
的右节点为head
,从而得到循环链表。
Code-Structure:
DFS(cur):
- 递归基:
- 节点
cur
为None
,则return
- 左递归:
DFS(cur.left)
- 处理根节点(cur):
- 当
self.pre
为None
时,为中序遍历达到最左侧的节点,保存为self.head
- 当
self.pre
不为None
时,更改cur
和self.pre
指针得到双向链表。 - 更新
self.pre
,最后指向末节点。
- 右递归:
DFS(cur.right)
Main:
- 特判:
if not root: return None
- 初始化
self.pre
为None
- 中序遍历得到双向链表,
self.pre
和self.head
- 由
self.pre
和self.head
得到循环链表 - 返回
self.head
P.S.图解可参看这篇文章
代码
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
#中序遍历
def DFS(cur):
if not cur: return #递归基
DFS(cur.left)#left
#处理root:构建链表
if self.pre:#pre节点是否已经记录,不为None时修改指针得到双向链表
self.pre.right = cur
cur.left = self.pre
else:#pre节点为None,记录头结点(为得到循环链表)
self.head = cur
self.pre = cur#依次处理下个节点
DFS(cur.right)#right
if not root: return None#递归基
self.pre = None
DFS(root)#中序遍历
self.head.left = self.pre#得到循环链表
self.pre.right = self.head
return self.head