返回
剑指 Offer 36:二叉搜索树与双向链表的深度解析
前端
2023-12-18 23:32:58
一、题目
给定一个二叉搜索树,将其转化成一个双向链表。要求二叉搜索树转化后的双向链表仍旧是中序序列。
二、解题思路
解题的关键在于利用二叉搜索树的中序遍历。中序遍历的顺序是:左子树、根节点、右子树。因此,如果按照中序遍历的顺序来遍历二叉搜索树,则可以得到一个有序的序列。将该序列转换成一个双向链表即可。
1. 递归解法
一种常见的实现方法是使用递归算法。在递归函数中,首先将左子树转换成双向链表,然后将根节点连接到左子树的最后一个节点后面,最后将右子树转换成双向链表并连接到根节点后面。这样就得到了一个完整的双向链表。
2. 迭代解法
除了递归解法之外,还可以使用迭代算法来实现。迭代算法的实现方式是使用一个栈来存储当前需要处理的节点。首先将二叉搜索树的根节点压入栈中,然后依次弹出栈顶节点,将其转换成双向链表,并将其连接到已经转换好的双向链表中。这样,最终就可以得到一个完整的双向链表。
三、具体实现
1. 递归实现
def convert_bst_to_dll(root):
if not root:
return None
# 将左子树转换成双向链表
left_dll = convert_bst_to_dll(root.left)
# 将右子树转换成双向链表
right_dll = convert_bst_to_dll(root.right)
# 将根节点连接到左子树的最后一个节点后面
if left_dll:
left_dll.right = root
root.left = left_dll
# 将右子树连接到根节点后面
if right_dll:
right_dll.left = root
root.right = right_dll
# 返回根节点
return root or left_dll
2. 迭代实现
def convert_bst_to_dll(root):
if not root:
return None
# 使用栈来存储需要处理的节点
stack = [root]
# 使用一个指针指向已经转换好的双向链表的最后一个节点
prev = None
# 循环处理栈中的节点
while stack:
# 弹出栈顶节点
node = stack.pop()
# 将该节点转换成双向链表
if prev:
prev.right = node
node.left = prev
# 将该节点的左子树压入栈中
if node.left:
stack.append(node.left)
# 将该节点的右子树压入栈中
if node.right:
stack.append(node.right)
# 更新 prev 指针
prev = node
# 返回已经转换好的双向链表的第一个节点
return prev
四、时间复杂度和空间复杂度
1. 时间复杂度
递归解法和迭代解法的時間复杂度都是O(n),其中n为二叉搜索树中的节点数。这是因为这两个算法都需要遍历二叉搜索树中的所有节点。
2. 空间复杂度
递归解法的空間复杂度为O(n),因为需要使用栈来存储节点。迭代解法的空間复杂度为O(1),因为不需要使用额外的空间。
五、结语
这篇文章深入分析了剑指 Offer 36:二叉搜索树与双向链表,通过详细的讲解和示例代码,帮助读者理解如何将一个二叉搜索树转化为一个双向链表。读者可以通过这篇博客文章,进一步加深对数据结构和算法的理解。