将排序链表转换为平衡BST

时间:2018-12-03 05:59:14

标签: java algorithm data-structures binary-search-tree

我正在处理以下面试问题:

  

给出一个单链列表,其中元素按升序排序   订单,将其转换为高度平衡的BST。

     

对于此问题,将高度平衡的二叉树定义为二叉树   每个节点的两个子树的深度从不变化的树   超过1。

我试图了解以下解决方案及其复杂性?有人可以帮助我了解其运作方式吗?下面的解是否为O(n)时间复杂度和O(log n)空间复杂度?

下面的算法也比“计算给定的链表中的节点数更好。让它为n。在计数节点之后,我们取左n / 2个节点并递归构造左子树。构造左子树后,我们为根分配内存,并将左侧的子树与根链接,最后,递归构造右侧的子树,并将其与根链接。在构造BST时,我们还不断将列表头指针移至下一个,以便在其中具有适当的指针。每个递归调用”

public TreeNode toBST(ListNode head) {
    if(head==null) return null;
    return helper(head,null);
}
public TreeNode helper(ListNode head, ListNode tail){
    ListNode slow = head;
    ListNode fast = head;
    if(head==tail) return null;

    while(fast!=tail && fast.next!=tail){
        fast = fast.next.next;
        slow = slow.next;
    }
    TreeNode thead = new TreeNode(slow.val);
    thead.left = helper(head,slow);
    thead.right = helper(slow.next,tail);
    return thead;
}

1 个答案:

答案 0 :(得分:3)

BST构造

可以通过将列表细分为两个等长的列表(其中中间的一个元素用作根),从排序后的列表构建平衡树。例如:

1.                       [1, 2, 3, 4, 5, 6, 7]


2.                               4
                           /           \
                       [1, 2, 3]     [5, 6, 7]


3.                               4
                            /          \
                           2           6
                          / \         / \
                          1  3        5  7

即使两个子列表相差一个元素,它们的高度最多也可以相差1,从而使树保持平衡。通过使用列表的中间元素,可以确保生成的树是BST,因为所有较小的元素都是左子树的一部分,而所有较大的元素都是右子树的所有元素。

slowfast

您的代码使用两个迭代器工作,其中一个(fast)在节点上的迭代速度是另一个(slow)的两倍。因此,当fast到达列表尾部或尾部之前的节点时,slow必须位于列表中间的节点处,从而将列表分为两个相同长度的子列表(最多不超过一个元素差异),然后可以按上图所示进行递归处理。

运行时复杂度

该算法在O(n lg n)中运行。让我们从辅助程序的重复开始:

T(n) = n / 2 + 2 * T(n / 2)
T(1) = 1

在每次helper调用中,我们必须找到由传递给helper的两个参数定义的链表的中间节点。这只能通过n / 2的步骤来完成,因为我们只能线性地遍历列表。另外,在原始列表大小的一半的链接列表上递归调用helper两次,以构建左右子树。

Master-theorem(案例2)应用于上述重复发生,我们得到O(n lg n)

空间复杂度

空间复杂性还需要考虑产生的输出结构。由于输入链接列表的每个元素都转换为BST中的一个节点,因此复杂度为O(n)

编辑

如果忽略输出,则空间复杂度仅取决于递归深度,而递归深度又为O(lg n),因此使空间复杂度为O(lg n)