繁体   English   中英

最大二叉树 (Leetcode) - 最优解解释?

[英]Maximum Binary Tree (Leetcode) - Optimal Solution Explanation?

我正在解决最大二叉树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数组并从nodes数组中弹出一次。 我试过用不同的示例输入运行它,但我正在努力连接点并围绕它的工作原理。 有人可以向我解释一下吗?

理解算法的一种方法是考虑循环不变量。 在这种情况下, 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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM