最大二叉树(Leetcode)-最佳解决方案说明?

时间:2020-10-10 20:48:14

标签: python algorithm time-complexity

我正在经历Maximum Binary Tree leetcode问题。 TL; DR是您有一个数组,例如:

[3,2,1,6,0,5]

您应该采用最大元素并使其成为树的根。然后将数组拆分为该元素左侧的部分和其右侧的部分,它们分别用于以相同的方式递归创建左侧和右侧子树。

LeetCode声称,最佳解决方案(在“解决方案”选项卡中显示)在每个递归步骤中均使用线性搜索子数组的最大值。在最坏的情况下,这是O(n ^ 2)。这是我想出的解决方案,很简单。

但是,我正在浏览其他提交的内容,找到了线性时间解决方案,但是我一直在努力了解其工作原理!看起来像这样:

def constructMaximumBinaryTree(nums):
    nodes=[]
    for num in nums:
        node = TreeNode(num)
        while nodes and num>nodes[-1].val:
            node.left = nodes.pop()
        if nodes:
            nodes[-1].right = node
        nodes.append(node)
        
    return nodes[0]

我已经分析了此函数,总的来说,这似乎是线性时间(O(n)),因为每个唯一节点最多只能添加到nodes数组中或从中弹出。我尝试使用不同的示例输入来运行它,但我一直在努力将各个点连接起来,并全神贯注于其工作原理。有人可以给我解释一下吗?

1 个答案:

答案 0 :(得分:0)

理解算法的一种方法是考虑循环不变性。在这种情况下,nodes的数组始终满足以下条件:每次执行for-loop之前和之后:

  1. nodes为空,并且最大二叉树不存在(例如,如果输入nums为空)
  2. nodes中的第一项是最大二叉树,它基于从输入nums到现在为止已处理的数据

while-loop确保当前最大二叉树是nodes数组中的第一项,否则,它将被弹出并添加为left子树。

for-loop的每次迭代中,检查:

if nodes:
    nodes[-1].right = node

将当前节点作为右子树添加到nodes数组的最后一项。并且,当发生这种情况时,当前节点小于nodes数组中的最后一个节点(因为每个输入整数都被定义为唯一)。并且由于当前节点小于数组中的最后一个节点,因此最后一个节点充当一个分区点,其值大于当前项目,这就是为什么将当前节点添加为右子树的原因。

nodes数组中有多个项目时,每个项目都是该项目左侧的子树。

运行时间

对于运行时间,让 n 为输入nums的长度。 for循环有 n 个执行。如果输入数据按降序排序,但最大输入值位于输入末尾(例如:4、3、2、1、5),则在每次迭代期间将跳过内部while循环,直到最后一个for循环迭代。在最后一个for循环迭代中,while循环将运行 n-1 次,总运行时间为 n +(n-1) => 2n-1 => O(n)

相关问题