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

Python 最大二叉树(Leetcode)-最佳解决方案说明?,python,algorithm,time-complexity,Python,Algorithm,Time Complexity,我正在处理leetcode问题。TL;DR是指您有一个数组,例如: [3,2,1,6,0,5] 你应该取最大元素,并将其作为树的根。然后将数组拆分为元素左侧的部分和元素右侧的部分,这些部分分别用于以相同的方式递归创建左侧和右侧子树 LeetCode声称最佳解决方案(显示在“解决方案”选项卡中)在每个递归步骤中使用线性搜索子数组的最大值。在最坏的情况下,这是O(n^2)。这就是我提出的解决方案,而且非常简单 然而,我在查看其他提交的资料时发现了一个线性时间解决方案,但我一直在努力理解它是如何工作

我正在处理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)),因为每个唯一的节点最多一次添加到
节点
数组并从中弹出。我试着用不同的示例输入来运行它,但我很难把这些点连接起来,并思考它是如何工作的。有人能给我解释一下吗?

< P >理解算法的一种方法是考虑循环不变量。在这种情况下,
节点的数组
始终满足以下条件,即在每次执行
for循环
之前和之后:

  • 节点
    为空且不存在最大二叉树(例如,如果输入
    nums
    为空)
  • nodes
    中的第一项是最大二叉树,它基于迄今为止从输入
    nums
  • while循环
    确保当前最大二叉树是
    节点
    数组中的第一项,否则,它将被弹出并添加为
    子树

    在循环的每次迭代过程中,检查:

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

    节点
    数组中有多个项时,每个项都是其左侧项的子树

    运行时间
    对于运行时间,让n为输入的长度
    nums
    。for循环有n次执行。如果输入数据按降序排序,但最大输入值位于输入的末尾(例如:4、3、2、1、5),则在每次迭代期间将跳过内部while循环,直到最后一次for循环迭代。在最后的for循环迭代中,while循环将运行n次- 1次,对于n+(n-1)=>2n- 1=o(n)的总运行时间。< > P > > P >理解该算法的一种方法是考虑循环不变量。在这种情况下,
    节点的数组
    始终满足以下条件,即在每次执行
    for循环
    之前和之后:

  • 节点
    为空且不存在最大二叉树(例如,如果输入
    nums
    为空)
  • nodes
    中的第一项是最大二叉树,它基于迄今为止从输入
    nums
  • while循环
    确保当前最大二叉树是
    节点
    数组中的第一项,否则,它将被弹出并添加为
    子树

    在循环的每次迭代过程中,检查:

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

    节点
    数组中有多个项时,每个项都是其左侧项的子树

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