将二叉搜索树转化为排序的双向链表
约 587 字大约 2 分钟
2025-03-01
426. 将二叉搜索树转化为排序的双向链表
将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表 。
对于双向循环列表,你可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
特别地,我们希望可以 原地 完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中最小元素的指针。
示例 1:
输入:root = [4,2,5,1,3]
输出:[1,2,3,4,5]
解释:下图显示了转化后的二叉搜索树,实线表示后继关系,虚线表示前驱关系。
示例 2:
输入:root = [2,1,3]
输出:[1,2,3]
提示:
- 树中节点的数量在范围
[0, 2000]
中 -1000 <= Node.val <= 1000
- 树中的所有值都是 独一无二 的
双指针+递归中序遍历,无返回值无信息参数的DFS
first相当于虚拟头节点,负责保存头节点。last负责构建双向链表。
当有节点被处理时,将其添加到链表的末尾,并更新链表末尾的指针。
当第一个节点被处理时,将其记录为 first
,以便后续形成循环链表。
class Solution {
private Node first = null;
private Node last = null;
public Node treeToDoublyList(Node root) {
if (root == null) return null;
// 中序遍历树并构建链表
inOrder(root);
// 连接头尾节点形成循环链表
first.left = last;
last.right = first;
return first;
}
private void inOrder(Node node) {
if (node == null) return;
// 遍历左子树
inOrder(node.left);
// 处理当前节点
if (last != null) {
// 更新最后一个节点的右指针
last.right = node;
// 更新当前节点的左指针
node.left = last;
} else {
// 记录第一个节点,这个操作只会在处理第一个节点时执行。last永远前进,first确定后就不前进了。
first = node;
}
// 更新最后一个节点,last前进
last = node;
// 遍历右子树
inOrder(node.right);
}
}
- 时间复杂度O(n)
- 空间复杂度O(h)