Skip to content

Commit

Permalink
Validate Binary Search Tree
Browse files Browse the repository at this point in the history
  • Loading branch information
dksifoua committed Sep 22, 2024
1 parent 9ba2597 commit b175c69
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
| 0074 | Medium | Search a 2D Matrix | Array, Binary Search, Matrix | [solution](./docs/0074-Search-A-2D-Matrix.md) |
| 0076 | Hard | Minimum Window Substring | Hash Table, String, Sliding Window | [solution](./docs/0076-Mininum-Window-Substring.md) |
| 0084 | Hard | Largest Rectangle in Histogram | Array, Stack, Monotonic Stack | [solution](./docs/0084-Largest-Rectangle-In-Histogram.md) |
| 0098 | Medium | Validate Binary Search Tree | Tree, Depth-First Search, Binary Search Tree, Binary Tree | [solution](./docs/0098-Validate-Binary-Search-Tree.md) |
| 0100 | Easy | Same Tree | Tree, Depth-First Search, Breadth-First Search, Binary Tree | [solution](./docs/0100-Same-Tree.md) |
| 0102 | Medium | Binary Tree Level Order Traversal | Tree, Breadth-First Search, Binary Tree | [solution](./docs/0102-Binary-Tree-Level-Order-Traversal.md) |
| 0104 | Easy | Maximum Depth of Binary Tree | Tree, Depth-First Search, Breadth-First Search, Binary Tree | [solution](./docs/0104-Maximum-Depth-of-Binary-Tree.md) |
Expand Down
44 changes: 44 additions & 0 deletions docs/0098-Validate-Binary-Search-Tree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/description/)

## Intuition

To validate whether a binary tree is a binary search tree (BST), we need to ensure that each node satisfies the BST
property:

1. The left subtree of a node contains only nodes with keys less than the node’s key.
2. The right subtree of a node contains only nodes with keys greater than the node’s key.

The problem can be approached using a breadth-first search (BFS), where each node is checked against the valid range of
values it can have, derived from its parent nodes.

## Approach

1. **Breadth-First Search (BFS):**
- Use a queue to traverse the tree level by level.
- Each element in the queue is a tuple (`Tuple3<TreeNode, Long, Long>`) that contains:
- The current node.
- The valid minimum (`min`) value the node can have.
- The valid maximum (`max`) value the node can have.
- For each node, check whether its value lies within the valid range:
- If `node.value` is not within `[min, max]`, the tree is invalid, so return `false`.
- Otherwise, update the range for the left and right children:
- Left child: `max` becomes the value of the current node.
- Right child: `min` becomes the value of the current node.
2. **Return True for a Valid BST:** If the queue becomes empty without finding any violations of the BST property,
return `true`.

## Complexity

- **Time Complexity: `O(n)`**, where `n` is the number of nodes in the tree. Each node is processed once.
- **Space Complexity: `O(n)`**, for the queue, which may contain up to `n` nodes in the worst case (e.g., a complete
binary tree).

## Code

- [Java](../src/main/java/io/dksifoua/leetcode/validatebinarysearchtree/Solution.java)

## Summary

This BFS solution ensures each node is validated against the BST property by maintaining a valid range for its values,
derived from its parent nodes. The use of a queue and tuples makes the implementation clear and avoids recursion stack
overhead, providing an efficient `O(n)` time complexity.
4 changes: 4 additions & 0 deletions src/main/java/io/dksifoua/leetcode/utils/Tuple3.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.dksifoua.leetcode.utils;

public record Tuple3<T, U, V>(T first, U second, V third) {
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.dksifoua.leetcode.validatebinarysearchtree;

import io.dksifoua.leetcode.utils.TreeNode;
import io.dksifoua.leetcode.utils.Tuple3;

import java.util.LinkedList;
import java.util.Queue;

public class Solution {

public boolean isValidBST(TreeNode root) {
if (root == null) return true;

Queue<Tuple3<TreeNode, Long, Long>> queue = new LinkedList<>() {{
add(new Tuple3<>(root, Long.MIN_VALUE, Long.MAX_VALUE));
}};
while (!queue.isEmpty()) {
Tuple3<TreeNode, Long, Long> tuple3 = queue.remove();
TreeNode node = tuple3.first();
long min = tuple3.second(), max = tuple3.third();

if (node.getValue() <= min || node.getValue() >= max) return false;

if (node.getLeft() != null) queue.add(new Tuple3<>(node.getLeft(), min, (long) node.getValue()));
if (node.getRight() != null) queue.add(new Tuple3<>(node.getRight(), (long) node.getValue(), max));
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.dksifoua.leetcode.validatebinarysearchtree;

import io.dksifoua.leetcode.utils.TreeNode;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class SolutionTest {

final Solution solution = new Solution();

@Test
void test1() {
assertTrue(solution.isValidBST(TreeNode.build(new Integer[] { 2, 1, 3 })));
}

@Test
void test2() {
assertFalse(solution.isValidBST(TreeNode.build(new Integer[] { 5, 1, 4, null, null, 3, 6 })));
}

@Test
void test3() {
assertTrue(solution.isValidBST(TreeNode.build(new Integer[] { 2147483647 })));
}

@Test
void test4() {
assertFalse(solution.isValidBST(TreeNode.build(new Integer[] { 2, 2, 2 })));
}
}

0 comments on commit b175c69

Please sign in to comment.