Given a binary tree root, a node X in the tree is named good if in the path from root to X there are no nodes with a value greater than X.
Return the number of good nodes in the binary tree.
Example 1:
Input: root = [3,1,4,3,null,1,5]
Output: 4
Explanation: Nodes in blue are good.
Root Node (3) is always a good node.
Node 4 -> (3,4) is the maximum value in the path starting from the root.
Node 5 -> (3,4,5) is the maximum value in the path
Node 3 -> (3,1,3) is the maximum value in the path.
Example 2:
Input: root = [3,3,null,4,2]
Output: 3
Explanation: Node 2 -> (3, 3, 2) is not good, because "3" is higher than it.
Example 3:
Input: root = [1]
Output: 1
Explanation: Root is considered as good.
Constraints:
The number of nodes in the binary tree is in the range [1, 10^5].
Each node's value is between [-10^4, 10^4].
Solutions
Solution 1
Thinking
A node is good if nothing larger appears on the path from the root. \(n\le 10^5\). DFS carries the path maximum \(mx\); count the node when its value is at least \(mx\), then update \(mx\).
1 2 3 4 5 6 7 8 9101112131415161718192021
# 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 = rightclassSolution:defgoodNodes(self,root:TreeNode)->int:defdfs(root:TreeNode,mx:int):ifrootisNone:returnnonlocalansifmx<=root.val:ans+=1mx=root.valdfs(root.left,mx)dfs(root.right,mx)ans=0dfs(root,-1000000)returnans
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcgoodNodes(root*TreeNode)(ansint){vardfsfunc(*TreeNode,int)dfs=func(root*TreeNode,mxint){ifroot==nil{return}ifmx<=root.Val{ans++mx=root.Val}dfs(root.Left,mx)dfs(root.Right,mx)}dfs(root,-10001)return}
A node is good when no larger value appears on the path from the root. With \(n\) up to \(10^5\), one walk that carries the path maximum \(mx\) is enough: count the node when its value is at least \(mx\), then update \(mx\).
The walk enters the left child first. A left chain can be \(n\) nodes long, so recursion overflows before the count is finished. Each node is compared only with the maximum on its own path, so the two children do not depend on each other.
The nodes still to visit fit on an explicit stack together with the \(mx\) from above. After a pop, a value at least \(mx\) is counted and \(mx\) becomes that value; the right child is pushed, then the left child, both with this \(mx\), so the left child is handled first.
The initial \(mx\) is below the lower bound \(-10^4\), so the root is always good. Each node is pushed once.
1 2 3 4 5 6 7 8 91011121314151617181920
# 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 = rightclassSolution:defgoodNodes(self,root:TreeNode)->int:ans=0stk=[(root,-1000000)]whilestk:node,mx=stk.pop()ifnodeisNone:continueifmx<=node.val:ans+=1mx=node.valstk.append((node.right,mx))stk.append((node.left,mx))returnans
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcgoodNodes(root*TreeNode)(ansint){stk:=[]struct{node*TreeNodemxint}{{root,-10001}}forlen(stk)>0{cur:=stk[len(stk)-1]stk=stk[:len(stk)-1]node,mx:=cur.node,cur.mxifnode==nil{continue}ifmx<=node.Val{ans++mx=node.Val}stk=append(stk,struct{node*TreeNodemxint}{node.Right,mx},struct{node*TreeNodemxint}{node.Left,mx})}return}