计算好节点的数量

Posted

技术标签:

【中文标题】计算好节点的数量【英文标题】:Count Number of Good Nodes 【发布时间】:2022-01-11 09:22:32 【问题描述】:

problem statement

我无法理解我的代码有什么问题并理解下面的约束。

我的伪代码:

    遍历树的 Level Order 并构造数组表示(输入实际上是作为单个根给出的,但它们使用数组表示来显示完整的树) 遍历此数组表示,跳过空节点 对于每个节点,我们称其为 X,向上迭代直到到达根节点,检查路径中是否有任何点,parentNode > nodeX,这意味着 nodeX 不是一个好节点。 如果节点正常则增加计数器

约束:

二叉树的节点数在 [1, 10^5] 范围内。 每个节点的值都在 [-10^4, 10^4] 之间

首先: 我对约束的困惑是,自动化测试正在提供诸如[2,4,4,4,null,1,3,null,null,5,null,null,null,null,5,4,4] 之类的输入,如果我们遵循孩子位于c1 = 2k+1c2 = 2k+2parent = (k-1)//2 的规则,那么这意味着存在具有值@ 的节点987654329@

其次: 对于上面的输入,我的代码输出8,期望值是6,但是当我从数组中画树的时候,我也觉得答案应该是8!

tree of input

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def goodNodes(self, root: TreeNode) -> int:
        
        
        arrRepresentation = []
        
        queue = []
        
        queue.append(root)
        
        # while queue not empty
        while queue:
            # remove node
            node = queue.pop(0)
            if node is None:
                arrRepresentation.append(None)
                
            else:
                arrRepresentation.append(node.val)

            
          
            if node is not None:
                # add left to queue
                queue.append(node.left)

                # add right to queue
                queue.append(node.right)
            
        
        print(arrRepresentation)
        goodNodeCounter = 1

                
        # iterate over array representation of binary tree
        for k in range(len(arrRepresentation)-1, 0, -1):
            child = arrRepresentation[k]
            if child is None:
                continue
            isGoodNode = self._isGoodNode(k, arrRepresentation)
            print('is good: ' + str(isGoodNode))

            if isGoodNode:
                goodNodeCounter += 1
                
           
                
            
        
        return goodNodeCounter

        
    def _isGoodNode(self, k, arrRepresentation):
        
        child = arrRepresentation[k]
        print('child: '+str(child))
        # calculate index of parent
        parentIndex = (k-1)//2
        
        isGood = True
        # if we have not reached root node
        while parentIndex >= 0:
            parent = arrRepresentation[parentIndex]
            print('parent: '+ str(parent))
            # calculate index of parent
            parentIndex = (parentIndex-1)//2
            
            if parent is None:
                continue
            
            if parent > child:
                isGood = False
                break
                
           
                
        return isGood
        
        
        

【问题讨论】:

你应该从问题陈述开始。如果没有这种上下文,您的混淆或伪代码对读者来说意义不大。 至于第二个问题,我觉得你画错了树。直到第三级(即,4、1、3),树是正确的。但那一定是 5 是 1 的孩子,然后另一个 5 是这个 5 的孩子。那么 4 和 4 是最后 5 的孩子。 表示树的数组称为二叉堆。空条目表示没有子项(不是该值为空)。看这里:en.wikipedia.org/wiki/Heap_(data_structure) 【参考方案1】:

您提供的binary heap 对应于以下层次结构:

tree = [2,4,4,4,None,1,3,None,None,5,None,None,None,None,5,4,4]
printHeapTree(tree)

    2
   / \
  4   4
 /   / \
4   1   3
         \
          5

在该树中,只有项目值1 的祖先大于自身。其他 6 个节点都很好,因为它们没有比自己更大的祖先(将根视为好)。

请注意,列表中的某些值无法访问,因为它们的父级为 null (None),因此它们不是树的一部分(但这可能是复制/粘贴错误)。如果我们将这些 None 值替换为其他值以使它们成为树的一部分,我们可以看到不可达节点在层次结构中的位置:

t = [2,4,4,4,'*', 1,3,'*',None, 5,None, None,None,None,5,4,4]
printHeapTree(t)

          2
       __/ \_
      4      4
     / \    / \
    4   *  1   3
   /   /        \
  *   5          5
 / \
4   4

这可能是 8(不计根为好)与 6(计为好)的结果之间的差异的原因。

你可以找到 printHeapTree() 函数here。

【讨论】:

【参考方案2】:

递归可能更容易:

class Node:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def good_nodes(root, maximum=float('-inf')):
    if not root: # null-root
        return 0

    is_this_good = maximum <= root.val # is this root a good node?

    maximum = max(maximum, root.val) # update max
    good_from_left = good_nodes(root.left, maximum) if root.left else 0
    good_from_right = good_nodes(root.right, maximum) if root.right else 0

    return is_this_good + good_from_left + good_from_right

tree = Node(2, Node(4, Node(4)), Node(4, Node(1, Node(5, None, Node(5, Node(4), Node(4)))), Node(3)))
print(good_nodes(tree)) # 6

基本上,递归遍历树,同时更新到目前为止看到的最大数量。在每次迭代中,将根的值与最大值进行比较,必要时增加计数器。

【讨论】:

你是怎么得到这棵树的?我认为当用 0 索引数组表示一棵树时,节点 k 的子节点将位于 2k+12k+2 @MPC 您将孩子放在“空”节点下。我认为那些“空”只是表示那里没有节点。所以我在分配孩子时跳过了那些空节点。请注意,例如,我的树中的前 5 个没有左孩子,在列表符号中用“null”表示。

以上是关于计算好节点的数量的主要内容,如果未能解决你的问题,请参考以下文章

1530. 好叶子节点对的数量

已知树中非叶子节点的度数和数量,如何计算树中叶子节点的个数?

leetcode 5474——好叶子节点对的数量

计算 Laravel Eloquent 中所有根父节点的所有第 n 个子节点的数量

如何减少Exadata计算节点CPU的Core数量

矩阵求幂,用于计算可能的路线数量