• Leetcode日练笔记41 [二叉树recursion专题] #250 Count Univalue Subtrees /Medium {Python}


    Given the root of a binary tree, return the number of uni-value 

    subtrees

    .

    uni-value subtree means all nodes of the subtree have the same value.

    Example 1:

    Input: root = [5,1,5,5,5,null,5]
    Output: 4
    

    Example 2:

    Input: root = []
    Output: 0
    

    Example 3:

    Input: root = [5,5,5,5,5,null,5]
    Output: 6
    

    Constraints:

    • The number of the node in the tree will be in the range [0, 1000].
    • -1000 <= Node.val <= 1000

    Thought process:

    Instinctively I take the main funciton countUnivalSubtrees as the one that should be recurred. So I divide the function into usual parts: one for base case which has no child nodes, automatically being a unival subtree, therefore counting as one; the rest part for recursive. 

    1. # Definition for a binary tree node.
    2. # class TreeNode:
    3. # def __init__(self, val=0, left=None, right=None):
    4. # self.val = val
    5. # self.left = left
    6. # self.right = right
    7. class Solution:
    8. def countUnivalSubtrees(self, root: Optional[TreeNode]) -> int:
    9. if not root: return 0
    10. if not root.left and not root.right: return 1
    11. if not root.left:
    12. if root.right.val == root.val:
    13. return 1 + self.countUnivalSubtrees(root.right)
    14. else:
    15. return self.countUnivalSubtrees(root.right)
    16. if not root.right:
    17. if root.left.val == root.val:
    18. return 1 + self.countUnivalSubtrees(root.left)
    19. else:
    20. return self.countUnivalSubtrees(root.left)
    21. if root.right.val == root.val and root.left.val == root.val:
    22. return 1 + self.countUnivalSubtrees(root.right) + self.countUnivalSubtrees(root.left)
    23. else:
    24. return self.countUnivalSubtrees(root.right) + self.countUnivalSubtrees(root.left)

    However, it misses the scenerio that even when the node of interest has the same value as its child node, it doesn't necessarily mean its child node itself is also a unival subtree. In such case, the node of interest may violate the rule of being a unival subree. So we can't use this approach.

    Just like the graph shown below. This approach takes the root node 1 as unival subtree bc both its children nodes have the same value as it, which should not be by definition.

    Therefore, we have to separate the responsibilities: 1)identify whether the node of interest is a unival subtree by traversing all its children nods n comparing their value; 2) count the nodes that are satisfied such criteria.

    1. # Definition for a binary tree node.
    2. # class TreeNode:
    3. # def __init__(self, val=0, left=None, right=None):
    4. # self.val = val
    5. # self.left = left
    6. # self.right = right
    7. class Solution:
    8. def countUnivalSubtrees(self, root: Optional[TreeNode]) -> int:
    9. self.count = 0
    10. def is_a_uni_value_subtree(node)-> bool:
    11. if not node: return True
    12. isLeftUniValue = is_a_uni_value_subtree(node.left)
    13. isRightUniValue = is_a_uni_value_subtree(node.right)
    14. if isLeftUniValue and isRightUniValue:
    15. if node.left and node.left.val != node.val:
    16. return False
    17. if node.right and node.right.val != node.val:
    18. return False
    19. self.count += 1
    20. return True
    21. return False
    22. is_a_uni_value_subtree(root)
    23. return self.count

    Explanation:
     

    Here, the recursive calls are part of a conditional and statement. The nature of the and operator in Python (and many other languages) is short-circuiting. This means that if the first condition (is_a_uni_value_subtree(node.left)) evaluates to False, the second condition (is_a_uni_value_subtree(node.right)) will not be evaluated at all.

    This short-circuiting can lead to parts of the tree not being visited. Specifically, if any node's left subtree is not a uni-value subtree, the right subtree won't even be checked, leading to potential uni-value subtrees being missed.

    So, in the second code, the recursive exploration of the tree can be prematurely halted due to the short-circuiting behavior of the and operator, leading to a different (and likely incorrect) count of uni-value subtrees.

    That's why we need to run both left child node and right child node first then put them into the conditional statement. So that we won't miss counting the right child node even the left child node is not a unival subtree.

  • 相关阅读:
    基于Java微信小程序民宿短租系统设计和实现(源码+LW+调试文档+讲解等)
    ‘setuptools‘ is a dependency of conda and cannot be removed from
    java计算机毕业设计郑工社团交流服务信息平台源码+mysql数据库+系统+lw文档+部署
    作为一名外贸业务员,如何正确跟进客户?
    JVS开发套件产品定位
    关于Google推出的AAB,你了解多少
    单链表在线OJ题二(详解+图解)
    一、Redis入门之——介绍、安装,图形化界面(GUI)工具Redis Desktop Manager (RDM)安装
    Mongodb数据库
    Redis主从集群
  • 原文地址:https://blog.csdn.net/Bittersweet_t/article/details/132507125