Skip to content

Commit d9a1a6d

Browse files
Problem 98 (#37)
* add solution and resources * update readme
1 parent 2369708 commit d9a1a6d

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ As I work through this list I figure I would make a GitHub repo with my solution
4747
36. [Coin Change #322](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/coin-change-322.md)
4848
37. [Product of Array Except Self #238](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/product-of-array-238.md)
4949
38. [Min Stack #155](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/min-stack-155.md)
50-
39. Validate Binary Search Tree #98
50+
39. [Validate Binary Search Tree #98](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/validate-binary-tree-98.md)
5151
40. Number of Islands #200
5252
41. Rotting Oranges #994
5353
42. Search in Rotated Sorted Array #33
@@ -130,6 +130,7 @@ In order to practice with similar data structures I'll be placing each problem i
130130
- [Maximum Depth of Binary Tree #104](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/depth-binary-tree-104.md)
131131
- [Evaluate Reverse Polish Notation #150](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/polish-notation-150.md)
132132
- [Min Stack #155](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/min-stack-155.md)
133+
- [Validate Binary Search Tree #98](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/validate-binary-tree-98.md)
133134

134135
### Linked Lists
135136

@@ -165,6 +166,7 @@ In order to practice with similar data structures I'll be placing each problem i
165166
- [Diameter of Binary Tree #543](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/diameter-binary-tree-543.md)
166167
- [Maximum Depth of Binary Tree #104](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/depth-binary-tree-104.md)
167168
- [Binary Tree Level Order Traversal #102](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/binary-tree-level-102.md)
169+
- [Validate Binary Search Tree #98](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/validate-binary-tree-98.md)
168170

169171
### Graph
170172

@@ -227,6 +229,7 @@ Within the problems above there are several patterns that often occur. I plan to
227229
- [Clone Graph #133](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/clone-graph-133.md)
228230
- [Number of Provinces #547](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/number-of-provinces-547.md)
229231
- [Course Schedule #207](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/course-schedule-207.md)
232+
- [Validate Binary Search Tree #98](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/validate-binary-tree-98.md)
230233

231234
### Divide & Conquer
232235

medium/validate-binary-tree-98.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Validate Binary Search Tree
2+
3+
Page on leetcode: https://leetcode.com/problems/validate-binary-search-tree/
4+
5+
## Problem Statement
6+
7+
Given the root of a binary tree, determine if it is a valid binary search tree (BST).
8+
9+
A valid BST is defined as follows:
10+
11+
- The left subtree of a node contains only nodes with keys less than the node's key.
12+
- The right subtree of a node contains only nodes with keys greater than the node's key.
13+
- Both the left and right subtrees must also be binary search trees.
14+
15+
### Constraints
16+
17+
- The number of nodes in the tree is in the range [1, 104].
18+
- -231 <= Node.val <= 231 - 1
19+
20+
### Example
21+
22+
```
23+
Input: root = [2,1,3]
24+
Output: true
25+
```
26+
27+
## Solution
28+
29+
- Probably use DFS to traverse the tree
30+
- Might be able to exit early if we find any node that doesn't satisfy BST
31+
- if null return
32+
- if left and right val are null return true
33+
- if left < val or left == null and right > val or right == null return true
34+
- else return false
35+
36+
### Pseudocode
37+
38+
1. base case if root is null return true
39+
2. l = dfs(left) and r = dfs(right)
40+
3. if left and right are null return true
41+
4. if left.val < val or left == null and right.val > val or right == null and l and r are true return true
42+
5. else return false
43+
44+
### Initial Attempt
45+
46+
```javascript
47+
const isValidBST = function (root) {
48+
if (!root) {
49+
return true;
50+
}
51+
const l = isValidBST(root.left);
52+
const r = isValidBST(root.right);
53+
const lVal = root.left ? root.left.val < root.val : true;
54+
const rVal = root.right ? root.right.val > root.val : true;
55+
56+
if (lVal && rVal && l && r) {
57+
return true;
58+
} else {
59+
return false;
60+
}
61+
};
62+
```
63+
64+
### Optimized Solution
65+
66+
The time and space complexity for both solutions below is O(n). Using in order traversal is likely a better approach. You can see an explanation of this solution here: https://www.youtube.com/watch?v=s6ATEkipzow
67+
68+
```javascript
69+
// Recursive DFS
70+
const isValidBST = function (root) {
71+
function valid(root, left, right) {
72+
// Base case, null node is true
73+
if (!root) {
74+
return true;
75+
}
76+
// Recursive calls on left and right nodes passing update "boundaries"
77+
const lNode = valid(root.left, left, root.val);
78+
const rNode = valid(root.right, root.val, right);
79+
80+
// Check that current node satisfies boundaries and child nodes are BST
81+
if (left < root.val && right > root.val && lNode && rNode) {
82+
return true;
83+
}
84+
85+
return false;
86+
}
87+
88+
return valid(root, -Infinity, Infinity);
89+
};
90+
91+
// In order traversal
92+
const isValidBST = function (root) {
93+
// Create the empty stack and set previous to null
94+
const stack = [];
95+
let prev = null;
96+
97+
while (root !== null || stack.length > 0) {
98+
// Traverse down the left nodes as far as possible and add to stack
99+
while (root !== null) {
100+
stack.push(root);
101+
root = root.left;
102+
}
103+
104+
root = stack.pop();
105+
// Checking if the previous value is larger than current, if it is then this is not a BST
106+
if (prev !== null && prev.val >= root.val) {
107+
return false;
108+
}
109+
// Update previous to the current root and then move root to the right
110+
prev = root;
111+
root = root.right;
112+
}
113+
// If we make it all the way here and didn't return false then it is a BST
114+
return true;
115+
};
116+
```

0 commit comments

Comments
 (0)