Skip to content

Problem 98 #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ As I work through this list I figure I would make a GitHub repo with my solution
36. [Coin Change #322](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/coin-change-322.md)
37. [Product of Array Except Self #238](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/product-of-array-238.md)
38. [Min Stack #155](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/min-stack-155.md)
39. Validate Binary Search Tree #98
39. [Validate Binary Search Tree #98](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/validate-binary-tree-98.md)
40. Number of Islands #200
41. Rotting Oranges #994
42. Search in Rotated Sorted Array #33
Expand Down Expand Up @@ -130,6 +130,7 @@ In order to practice with similar data structures I'll be placing each problem i
- [Maximum Depth of Binary Tree #104](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/easy/depth-binary-tree-104.md)
- [Evaluate Reverse Polish Notation #150](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/polish-notation-150.md)
- [Min Stack #155](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/min-stack-155.md)
- [Validate Binary Search Tree #98](https://github.com/curtisbarnard/leetcode-grind75-javascript/blob/main/medium/validate-binary-tree-98.md)

### Linked Lists

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

### Graph

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

### Divide & Conquer

Expand Down
116 changes: 116 additions & 0 deletions medium/validate-binary-tree-98.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Validate Binary Search Tree

Page on leetcode: https://leetcode.com/problems/validate-binary-search-tree/

## Problem Statement

Given the root of a binary tree, determine if it is a valid binary search tree (BST).

A valid BST is defined as follows:

- The left subtree of a node contains only nodes with keys less than the node's key.
- The right subtree of a node contains only nodes with keys greater than the node's key.
- Both the left and right subtrees must also be binary search trees.

### Constraints

- The number of nodes in the tree is in the range [1, 104].
- -231 <= Node.val <= 231 - 1

### Example

```
Input: root = [2,1,3]
Output: true
```

## Solution

- Probably use DFS to traverse the tree
- Might be able to exit early if we find any node that doesn't satisfy BST
- if null return
- if left and right val are null return true
- if left < val or left == null and right > val or right == null return true
- else return false

### Pseudocode

1. base case if root is null return true
2. l = dfs(left) and r = dfs(right)
3. if left and right are null return true
4. if left.val < val or left == null and right.val > val or right == null and l and r are true return true
5. else return false

### Initial Attempt

```javascript
const isValidBST = function (root) {
if (!root) {
return true;
}
const l = isValidBST(root.left);
const r = isValidBST(root.right);
const lVal = root.left ? root.left.val < root.val : true;
const rVal = root.right ? root.right.val > root.val : true;

if (lVal && rVal && l && r) {
return true;
} else {
return false;
}
};
```

### Optimized Solution

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

```javascript
// Recursive DFS
const isValidBST = function (root) {
function valid(root, left, right) {
// Base case, null node is true
if (!root) {
return true;
}
// Recursive calls on left and right nodes passing update "boundaries"
const lNode = valid(root.left, left, root.val);
const rNode = valid(root.right, root.val, right);

// Check that current node satisfies boundaries and child nodes are BST
if (left < root.val && right > root.val && lNode && rNode) {
return true;
}

return false;
}

return valid(root, -Infinity, Infinity);
};

// In order traversal
const isValidBST = function (root) {
// Create the empty stack and set previous to null
const stack = [];
let prev = null;

while (root !== null || stack.length > 0) {
// Traverse down the left nodes as far as possible and add to stack
while (root !== null) {
stack.push(root);
root = root.left;
}

root = stack.pop();
// Checking if the previous value is larger than current, if it is then this is not a BST
if (prev !== null && prev.val >= root.val) {
return false;
}
// Update previous to the current root and then move root to the right
prev = root;
root = root.right;
}
// If we make it all the way here and didn't return false then it is a BST
return true;
};
```