返回

解析 LeetCode 109:有序链表转换二叉搜索树,掌握算法之美

前端

在展开详细分析之前,让我们先来明确一下什么是高度平衡的二叉搜索树。高度平衡意味着二叉搜索树的任意节点的左右子树高度差绝对值不超过 1。这样的树不仅结构稳定,而且搜索效率极佳。

算法概述

我们采用的算法思路分而治之,即先将有序链表分成左右两个部分,然后分别将它们转换成左子树和右子树,最后将它们与根节点连接起来,形成一颗平衡的二叉搜索树。这个过程可以递归地进行,直到所有节点都已处理完毕。

具体步骤

  1. 寻找链表中间节点

    • 将快慢指针同时指向链表头节点。
    • 快指针一次移动两步,慢指针一次移动一步。
    • 当快指针到达链表尾部时,慢指针所指的节点就是链表的中间节点。
    • 将中间节点设置为根节点。
  2. 递归处理左子树和右子树

    • 将链表从头节点到中间节点的前一个节点断开,这样就得到了左子链表。
    • 将链表从中间节点的下一个节点到尾节点断开,这样就得到了右子链表。
    • 对左子链表和右子链表分别应用相同的步骤,直到它们都变成空链表。
  3. 将左子树、右子树与根节点连接起来

    • 将左子树作为根节点的左子树。
    • 将右子树作为根节点的右子树。
  4. 返回根节点

    • 返回根节点,即已转换完成的二叉搜索树。

复杂度分析

  • 时间复杂度:O(n log n)。
  • 空间复杂度:O(log n)。

代码实现

def sorted_list_to_bst(head):
    """
    将一个按升序排列的单链表转换成高度平衡的二叉搜索树。

    参数:
    head:链表头节点

    返回:
    二叉搜索树的根节点
    """
    # 寻找链表中间节点
    slow, fast = head, head.next
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

    # 中间节点作为根节点
    root = slow

    # 左子树为空
    if head == slow:
        return root

    # 断开链表
    prev = head
    while prev.next != slow:
        prev = prev.next
    prev.next = None

    # 左子树
    left = sorted_list_to_bst(head)

    # 右子树
    right = sorted_list_to_bst(slow.next)

    # 将左右子树与根节点连接起来
    root.left = left
    root.right = right

    return root

应用场景

有序链表转换二叉搜索树算法在许多场景中都有着广泛的应用,例如:

  • 将数据从一种格式转换为另一种格式,例如将有序链表转换为二叉搜索树。
  • 在内存有限的情况下,将数据存储在磁盘上,然后按需加载到内存中。
  • 在并行计算中,将数据分解成多个子任务,然后并行处理这些子任务。

拓展阅读