You are given the root of a binary tree. A node X in the tree is considered "good" if, in the path from the root to X, there are no nodes with a value greater than X. Your task is to return the number of "good" nodes in the binary tree.
For example:
[3,1,4,3,null,1,5]
. The good nodes are 3 (root), 4 (3->4), 5 (3->4->5), and 3 (3->1->3), so the output should be 4.[3,3,null,4,2]
, the good nodes are 3 (root), 3 (3->3), and 4 (3->3->4), so the output should be 3. The node '2' is not good because 3 > 2 in the path 3->3->2.[1]
, the root is considered good, so the output is 1.Write a function that efficiently determines the number of good nodes in a given binary tree. What is the time and space complexity of your solution? How would you handle an empty tree, or a tree where all nodes have the same value?
Given a binary tree root
, a node X in the tree is named good if in the path from the root to X there are no nodes with a value greater than X.
Return the number of good nodes in the binary tree.
A brute-force approach would involve traversing each path from the root to every node and checking if the current node is good based on the nodes encountered along the way.
Big O Runtime: O(NlogN) in balanced tree or O(N^2) in skewed tree, where N is the number of nodes. This is because, in the worst case, for each node, we might have to traverse a path of length N.
Big O Space: O(H), where H is the height of the tree. This is due to the recursive call stack.
A more efficient approach involves a Depth-First Search (DFS) while carrying the maximum value seen so far in the path from the root.
Big O Runtime: O(N), where N is the number of nodes in the tree, as each node is visited exactly once.
Big O Space: O(H), where H is the height of the tree, due to the recursion stack. In the worst case (skewed tree), H can be equal to N.
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:
def dfs(node, max_val):
if not node:
return 0
count = 0
if node.val >= max_val:
count = 1
max_val = node.val
count += dfs(node.left, max_val)
count += dfs(node.right, max_val)
return count
return dfs(root, root.val)