Skip to content

将二叉搜索树转化为排序的双向链表

约 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)