Skip to content

Commit fb32e20

Browse files
committed
Count Good Nodes in Binary Tree
1 parent f74573e commit fb32e20

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
| 0853 | Medium | Car Fleet | Array, Stack, Sorting, Monotonic Stack | [solution](./docs/0853-Car-Fleet.md) |
6060
| 0875 | Medium | Koko Eating Bananas | Array, Binary Search | [solution](./docs/0875-Koko-Eating-Bananas.md) |
6161
| 0981 | Medium | Time Based Key-Value Store | Hash Table, String, Binary Search, Design | [solution](./docs/0981-Time-Based-Key-Value-Store.md) |
62+
| 1448 | Medium | Count Good Nodes in Binary Tree | Tree, Depth-First Search, Breadth-First Search, Binary Tree | [solution](./docs/1448-Count-Good-Nodes-in-Binary-Tree.md) |
6263
| 1768 | Easy | Merge Strings Alternately | Two Pointers, String | [solution](./docs/1768-Merge-Strings-Alternately.md) |
6364

6465
![Alt](https://repobeats.axiom.co/api/embed/3071ed0c351defe6d37f0d25b516d3314bbf9f30.svg "RepoBeats analytics image")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# [Count Good Nodes in Binary Tree](https://leetcode.com/problems/count-good-nodes-in-binary-tree/description/)
2+
3+
## Intuition
4+
5+
A node in the binary tree is considered “good” if its value is greater than or equal to the maximum value encountered on
6+
the path from the root to that node. The problem can be solved efficiently using a Breadth-First Search (BFS) approach
7+
where we maintain the maximum value encountered so far at each level of traversal.
8+
9+
## Approach
10+
11+
1. **Breadth-First Search (BFS):**
12+
- Use a queue to traverse the binary tree level by level.
13+
- Each element in the queue is a tuple (`Tuple2<TreeNode, Integer>`) consisting of the current node and the maximum
14+
value observed from the root to that node.
15+
2. **Check for Good Nodes:**
16+
- For each node dequeued:
17+
- Compare its value with the maximum value in its path.
18+
- If the node’s value is greater than or equal to this maximum value, it is a good node, and we increment the
19+
result.
20+
- Update the maximum value for the path by taking the larger of the current node’s value and the previous
21+
maximum.
22+
- Enqueue the left and right children of the current node (if they exist) along with the updated maximum value.
23+
3. **Return the Result:** After completing the BFS traversal, result contains the total number of good nodes.
24+
25+
## Complexity
26+
27+
- **Time Complexity: `O(n)`, where `n` is the number of nodes in the tree. Each node is visited once during the
28+
traversal.
29+
- **Space Complexity: `O(n)`**, for the queue, which may hold up to `n` nodes in the worst case (e.g., for a complete
30+
binary tree).
31+
32+
## Code
33+
34+
- [Java](../src/main/java/io/dksifoua/leetcode/countgoodnodesinbinarytree/Solution.java)
35+
36+
## Summary
37+
38+
This BFS solution efficiently counts the “good” nodes in a binary tree by maintaining the maximum value along each path.
39+
Using a queue to traverse the tree ensures a level-by-level exploration, and the algorithm achieves optimal `O(n)` time
40+
complexity. The use of a tuple makes it easy to pass and update the maximum value dynamically during traversal.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.dksifoua.leetcode.countgoodnodesinbinarytree;
2+
3+
import io.dksifoua.leetcode.utils.TreeNode;
4+
import io.dksifoua.leetcode.utils.Tuple2;
5+
6+
import java.util.LinkedList;
7+
import java.util.Queue;
8+
9+
public class Solution {
10+
11+
public int goodNodes(TreeNode root) {
12+
int result = 0;
13+
if (root == null) return result;
14+
15+
Queue<Tuple2<TreeNode, Integer>> queue = new LinkedList<>() {{
16+
add(new Tuple2<>(root, Integer.MIN_VALUE));
17+
}};
18+
while (!queue.isEmpty()) {
19+
Tuple2<TreeNode, Integer> tuple2 = queue.remove();
20+
TreeNode node = tuple2.first();
21+
Integer maxValue = tuple2.second();
22+
23+
if (node.getValue() >= maxValue) {
24+
maxValue = node.getValue();
25+
result += 1;
26+
}
27+
28+
if (node.getLeft() != null) queue.add(new Tuple2<>(node.getLeft(), maxValue));
29+
if (node.getRight() != null) queue.add(new Tuple2<>(node.getRight(), maxValue));
30+
}
31+
32+
return result;
33+
}
34+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.dksifoua.leetcode.countgoodnodesinbinarytree;
2+
3+
import io.dksifoua.leetcode.utils.TreeNode;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Test;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
9+
public class SolutionTest {
10+
11+
final Solution solution = new Solution();
12+
13+
@Test
14+
void test1() {
15+
assertEquals(4, solution.goodNodes(TreeNode.build(new Integer[] { 3, 1, 4, 3, null, 1, 5 })));
16+
}
17+
18+
@Test
19+
void test2() {
20+
assertEquals(3, solution.goodNodes(TreeNode.build(new Integer[] { 3, 3, null, 4, 2 })));
21+
}
22+
23+
@Test
24+
void test3() {
25+
assertEquals(1, solution.goodNodes(TreeNode.build(new Integer[] { 1 })));
26+
}
27+
}

0 commit comments

Comments
 (0)