[英]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
之前和之后的条件,要么:
nodes
为空且最大二叉树不存在(例如,如果输入nums
为空)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.