def rob(root: Optional[TreeNode]) -> int:
def helper(root):
# if a empty node is reach return (0, 0)
if not root:
return(0, 0)
else:
max_left_children, max_left_grandchildren = helper(root.left) # amount on left subtree, best amount for children and grandchildren nodes
max_right_children, max_right_grandchildren = helper(root.right) # amount on right subtree, best amount for children and grandchildren nodes
max_rob_children = max_left_children + max_right_children # amount robbing left and right children
current_max = max(max_rob_children, root.val + max_left_grandchildren + max_right_grandchildren) # best amount for this house (node)
return(current_max, max_rob_children)
return(helper(root)[0])