Welcome to Subscribe On Youtube

1448. Count Good Nodes in Binary Tree

Description

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 2: Explicit Stack

Thinking

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.

  • /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode() {}
     *     TreeNode(int val) { this.val = val; }
     *     TreeNode(int val, TreeNode left, TreeNode right) {
     *         this.val = val;
     *         this.left = left;
     *         this.right = right;
     *     }
     * }
     */
    class Solution {
        private int ans = 0;
    
        public int goodNodes(TreeNode root) {
            dfs(root, -100000);
            return ans;
        }
    
        private void dfs(TreeNode root, int mx) {
            if (root == null) {
                return;
            }
            if (mx <= root.val) {
                ++ans;
                mx = root.val;
            }
            dfs(root.left, mx);
            dfs(root.right, mx);
        }
    }
    
    
    // Solution 2
    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode() {}
     *     TreeNode(int val) { this.val = val; }
     *     TreeNode(int val, TreeNode left, TreeNode right) {
     *         this.val = val;
     *         this.left = left;
     *         this.right = right;
     *     }
     * }
     */
    class Solution {
        public int goodNodes(TreeNode root) {
            int ans = 0;
            Deque<TreeNode> nodes = new ArrayDeque<>();
            Deque<Integer> limits = new ArrayDeque<>();
            if (root != null) {
                nodes.push(root);
                limits.push(-100000);
            }
            while (!nodes.isEmpty()) {
                TreeNode node = nodes.pop();
                int mx = limits.pop();
                if (mx <= node.val) {
                    ++ans;
                    mx = node.val;
                }
                if (node.right != null) {
                    nodes.push(node.right);
                    limits.push(mx);
                }
                if (node.left != null) {
                    nodes.push(node.left);
                    limits.push(mx);
                }
            }
            return ans;
        }
    }
    
    
  • /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
     * };
     */
    class Solution {
    public:
        int goodNodes(TreeNode* root) {
            int ans = 0;
            function<void(TreeNode*, int)> dfs = [&](TreeNode* root, int mx) {
                if (!root) {
                    return;
                }
                if (mx <= root->val) {
                    ++ans;
                    mx = root->val;
                }
                dfs(root->left, mx);
                dfs(root->right, mx);
            };
            dfs(root, -1e6);
            return ans;
        }
    };
    
    
    // Solution 2
    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
     * };
     */
    class Solution {
    public:
        int goodNodes(TreeNode* root) {
            int ans = 0;
            vector<pair<TreeNode*, int>> stk;
            stk.emplace_back(root, -1000000);
            while (!stk.empty()) {
                auto [node, mx] = stk.back();
                stk.pop_back();
                if (!node) {
                    continue;
                }
                if (mx <= node->val) {
                    ++ans;
                    mx = node->val;
                }
                stk.emplace_back(node->right, mx);
                stk.emplace_back(node->left, mx);
            }
            return ans;
        }
    };
    
    
  • # 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:
            def dfs(root: TreeNode, mx: int):
                if root is None:
                    return
                nonlocal ans
                if mx <= root.val:
                    ans += 1
                    mx = root.val
                dfs(root.left, mx)
                dfs(root.right, mx)
    
            ans = 0
            dfs(root, -1000000)
            return ans
    
    
    
    # Solution 2
    # 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:
            ans = 0
            stk = [(root, -1000000)]
            while stk:
                node, mx = stk.pop()
                if node is None:
                    continue
                if mx <= node.val:
                    ans += 1
                    mx = node.val
                stk.append((node.right, mx))
                stk.append((node.left, mx))
            return ans
    
    
  • /**
     * Definition for a binary tree node.
     * type TreeNode struct {
     *     Val int
     *     Left *TreeNode
     *     Right *TreeNode
     * }
     */
    func goodNodes(root *TreeNode) (ans int) {
    	var dfs func(*TreeNode, int)
    	dfs = func(root *TreeNode, mx int) {
    		if root == nil {
    			return
    		}
    		if mx <= root.Val {
    			ans++
    			mx = root.Val
    		}
    		dfs(root.Left, mx)
    		dfs(root.Right, mx)
    	}
    	dfs(root, -10001)
    	return
    }
    
    
    // Solution 2
    /**
     * Definition for a binary tree node.
     * type TreeNode struct {
     *     Val int
     *     Left *TreeNode
     *     Right *TreeNode
     * }
     */
    func goodNodes(root *TreeNode) (ans int) {
    	stk := []struct {
    		node *TreeNode
    		mx   int
    	}{{root, -10001}}
    	for len(stk) > 0 {
    		cur := stk[len(stk)-1]
    		stk = stk[:len(stk)-1]
    		node, mx := cur.node, cur.mx
    		if node == nil {
    			continue
    		}
    		if mx <= node.Val {
    			ans++
    			mx = node.Val
    		}
    		stk = append(stk, struct {
    			node *TreeNode
    			mx   int
    		}{node.Right, mx}, struct {
    			node *TreeNode
    			mx   int
    		}{node.Left, mx})
    	}
    	return
    }
    
    
  • /**
     * Definition for a binary tree node.
     * class TreeNode {
     *     val: number
     *     left: TreeNode | null
     *     right: TreeNode | null
     *     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
     *         this.val = (val===undefined ? 0 : val)
     *         this.left = (left===undefined ? null : left)
     *         this.right = (right===undefined ? null : right)
     *     }
     * }
     */
    
    function goodNodes(root: TreeNode | null): number {
        let ans = 0;
        const dfs = (root: TreeNode | null, mx: number) => {
            if (!root) {
                return;
            }
            if (mx <= root.val) {
                ++ans;
                mx = root.val;
            }
            dfs(root.left, mx);
            dfs(root.right, mx);
        };
        dfs(root, -1e6);
        return ans;
    }
    
    
    
    // Solution 2
    /**
     * Definition for a binary tree node.
     * class TreeNode {
     *     val: number
     *     left: TreeNode | null
     *     right: TreeNode | null
     *     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
     *         this.val = (val===undefined ? 0 : val)
     *         this.left = (left===undefined ? null : left)
     *         this.right = (right===undefined ? null : right)
     *     }
     * }
     */
    
    function goodNodes(root: TreeNode | null): number {
        let ans = 0;
        const stk: [TreeNode | null, number][] = [[root, -1e6]];
        while (stk.length) {
            const [node, limit] = stk.pop()!;
            if (!node) {
                continue;
            }
            let mx = limit;
            if (mx <= node.val) {
                ++ans;
                mx = node.val;
            }
            stk.push([node.right, mx]);
            stk.push([node.left, mx]);
        }
        return ans;
    }
    
    

All Problems

All Solutions