Compare commits

...
Author SHA1 Message Date
Prad Nukala 00f44a1c47 docs(docs): add MDX page for Merge k Sorted Lists problem 2026-09-14 12:50:08 -04:00
Prad Nukala 24312437eb feat(work): add solution for LeetCode 23 Merge k Sorted Lists 2026-09-14 12:49:55 -04:00
Prad Nukala 4c9c8f39ae feat(work): add solution for LeetCode 973 K Closest Points to Origin 2026-09-14 12:37:15 -04:00
Prad Nukala 88ff63f5c4 docs(docs): add MDX page for LeetCode 973 K Closest Points to Origin 2026-09-14 12:37:11 -04:00
Prad Nukala 2066856d15 feat(work): add solution for LeetCode 215 Kth Largest Element in an Array 2026-09-14 12:21:55 -04:00
Prad Nukala 393d72c9fe docs(docs): add MDX page for LeetCode 215 Kth Largest Element in an Array 2026-09-14 12:21:51 -04:00
Prad Nukala 6c18301aa6 feat(work): add Lowest Common Ancestor of BST solution 2026-09-05 16:33:03 -04:00
Prad Nukala 02f6a20cc1 docs(docs): add documentation for 235 Lowest Common Ancestor of a Binary Search Tree 2026-09-05 16:32:59 -04:00
Prad Nukala 9288aaa152 feat(work): add Kth Smallest Element in a BST solution 2026-09-05 16:28:21 -04:00
Prad Nukala d5ea71dbc1 docs(docs): add MDX page for “230. Kth Smallest Element in a BST” 2026-09-05 16:28:18 -04:00
Prad Nukala 3e1a66eb37 feat(work): add LeetCode solutions for 217, 271, and 98 2026-09-05 13:37:53 -04:00
Prad Nukala 9a2b80949b docs(docs): add 271 Encode/Decode Strings and 98 Validate BST pages 2026-09-05 13:37:42 -04:00
Prad Nukala 883dc69dba docs(docs): update index title from “Progress” to “Overview” 2026-09-04 16:49:23 -04:00
Prad Nukala e3f0b5420a docs(docs): replace index with live progress dashboard and delete redundant progress page 2026-09-04 16:46:50 -04:00
19 changed files with 920 additions and 16 deletions

No files matched your search

@@ -0,0 +1,41 @@
---
title: '215. Kth Largest Element in an Array'
description: Given an integer array nums and an integer k, return the k^th largest element in the array
sidebar:
label: 'Kth Largest Element in an Array'
badge: 'Medium'
---
<Badge variant="accent">Heap / Priority Queue</Badge>
### Example 1:
- Input: `nums = [3,2,1,5,6,4], k = 2`
- Output: `5`
### Example 2:
- Input: `nums = [3,2,3,1,2,4,5,5,6], k = 4`
- Output: `4`
### Constraints:
- `1 <= k <= nums.length <= 10^5`
- `-10^4 <= nums[i] <= 10^4`
## Solution
```py
import heapq
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
for i in range(len(nums)):
nums[i] = -nums[i]
heapq.heapify(nums)
for _ in range(k - 1):
heapq.heappop(nums)
return -heapq.heappop(nums)
```
@@ -42,7 +42,14 @@ flowchart TD
## Solution ## Solution
```js <CodeGroup>
```py Python
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
```
```js JavaScript
/** /**
* @param {number[]} nums * @param {number[]} nums
* @return {boolean} * @return {boolean}
@@ -59,6 +66,8 @@ var containsDuplicate = function(nums) {
}; };
``` ```
</CodeGroup>
## Explanation ## Explanation
<YouTube id="3OamzN90kPg" title="Contains Duplicate - Leetcode 217 - Python" /> <YouTube id="3OamzN90kPg" title="Contains Duplicate - Leetcode 217 - Python" />
@@ -0,0 +1,48 @@
---
title: '271. Encode and Decode Strings'
description: Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings
sidebar:
label: 'Encode and Decode Strings'
badge: 'Medium'
---
<Badge variant="accent">Array</Badge>
::::warning
Could you write a generalized algorithm to work on any possible set of characters?
::::
### Example 1:
- Input: `dummy_input = ["Hello","World"]`
- Output: `["Hello","World"]`
- Explanation: Machine `1`: Codec encoder = new Codec(); String msg = encoder.encode(strs); Machine `1` ---msg---> Machine `2` Machine `2`: Codec decoder = new Codec(); `String[] strs` = decoder.decode(msg);
### Example 2:
- Input: `dummy_input = [""]`
- Output: `[""]`
### Constraints:
- `1 <= strs.length <= 200`
- `0 <= strs[i].length <= 200`
- `strs[i]` contains any possible characters out of 256 valid ASCII characters.
## Solution
```py
class Codec:
def encode(self, strs: List[str]) -> str:
"""Encodes a list of strings to a single string.
"""
def decode(self, s: str) -> List[str]:
"""Decodes a single string to a list of strings.
"""
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(strs))
```
@@ -0,0 +1,48 @@
---
title: '973. K Closest Points to Origin'
description: Given an array of points where points[i] = [xi, yi] represents a point on the X-Y plane and an integer k, return the k closest points to the origin (0, 0)
sidebar:
label: 'K Closest Points to Origin'
badge: 'Medium'
---
<Badge variant="accent">Heap / Priority Queue</Badge>
### Example 1:
- Input: `points = [[1,3],[-2,2]], k = 1`
- Output: `[[-2,2]]`
- Explanation: The distance between `(1`, `3`) and the origin is sqrt(10). The distance between `(-2`, `2`) and the origin is sqrt(8). Since sqrt(8) < sqrt(10), `(-2`, `2`) is closer to the origin. We only want the closest `k = 1 points` from the origin, so the answer is just [[-2,2]].
### Example 2:
- Input: `points = [[3,3],[5,-1],[-2,4]], k = 2`
- Output: `[[3,3],[-2,4]]`
- Explanation: The answer [[-2,4],[3,3]] would also be accepted.
### Constraints:
- `1 <= k <= points.length <= 10^4`
- `-10^4 <= xi, yi <= 10^4`
## Solution
```py
import heapq
class Solution:
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
minHeap = []
for x, y in points:
dist = (x**2) + (y**2)
minHeap.append([dist, x, y])
heapq.heapify(minHeap)
res = []
while k > 0:
dist, x, y = heapq.heappop(minHeap)
res.append([x, y])
k -= 1
return res
```
@@ -0,0 +1,69 @@
---
title: '23. Merge k Sorted Lists'
description: You are given an array of k linked-lists lists, each linked-list is sorted in ascending order
sidebar:
label: 'Merge k Sorted Lists'
badge: 'Hard'
---
<Badge variant="accent">Heap / Priority Queue</Badge>
### Example 1:
- Input: `lists = [[1,4,5],[1,3,4],[2,6]]`
- Output: `[1,1,2,3,4,4,5,6]`
- Explanation: The linked-lists are: [ 1->4->5, 1->3->4, 2->6 ] merging them into one sorted linked list: 1->1->2->3->4->4->5->6
### Example 2:
- Input: `lists = []`
- Output: `[]`
### Example 3:
- Input: `lists = [[]]`
- Output: `[]`
### Constraints:
- `k == lists.length`
- `0 <= k <= 10^4`
- `0 <= lists[i].length <= 500`
- `-10^4 <= lists[i][j] <= 10^4`
- `lists[i]` is sorted in ascending order.
- The sum of lists[i].length will not exceed 10^4.
## Solution
```py
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
import heapq
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
heap = []
# K log K
for i, node in enumerate(lists):
if node:
heapq.heappush(heap, (node.val, i, node))
D = ListNode()
cur = D
# n log k
while heap:
val, i, node = heapq.heappop(heap)
cur.next = node
cur = node
node = node.next
if node:
heapq.heappush(heap, (node.val, i, node))
# Time: O(N log k)
# Space: O(n)
return D.next
```
@@ -0,0 +1,54 @@
---
title: '230. Kth Smallest Element in a BST'
description: Given the root of a binary search tree, and an integer k, return the k^th smallest value (1-indexed) of all the values of the nodes in the tree
sidebar:
label: 'Kth Smallest Element in a BST'
badge: 'Medium'
---
<Badge variant="accent">Binary Search Tree</Badge>
::::warning
If the BST is modified often (i.e., we can do insert and delete operations) and you need to find the kth smallest frequently, how would you optimize?
::::
### Example 1:
- Input: `root = [3,1,4,null,2], k = 1`
- Output: `1`
### Example 2:
- Input: `root = [5,3,6,2,4,null,null,1], k = 3`
- Output: `3`
### Constraints:
- The number of nodes in the tree is n.
- `1 <= k <= n <= 10^4`
- `0 <= Node.val <= 10^4`
## Solution
```py
# 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
n = 0
stack = []
cur = root
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
cur = stack.pop()
n += 1
if n == k:
return cur.val
cur = cur.right
```
@@ -0,0 +1,56 @@
---
title: '235. Lowest Common Ancestor of a Binary Search Tree'
description: Given a binary search tree (BST), find the lowest common ancestor (LCA) node of two given nodes in the BST
sidebar:
label: 'Lowest Common Ancestor of a Binary Search Tree'
badge: 'Medium'
---
<Badge variant="accent">Binary Search Tree</Badge>
### Example 1:
- Input: `root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8`
- Output: `6`
- Explanation: The LCA of nodes `2` and `8` is `6`.
### Example 2:
- Input: `root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4`
- Output: `2`
- Explanation: The LCA of nodes `2` and `4` is `2`, since a node can be a descendant of itself according to the LCA definition.
### Example 3:
- Input: `root = [2,1], p = 2, q = 1`
- Output: `2`
### Constraints:
- The number of nodes in the tree is in the range [2, 10^5].
- `-10^9 <= Node.val <= 10^9`
- All Node.val are unique.
- `p != q`
- p and q will exist in the BST.
## Solution
```py
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(
self, root: "TreeNode", p: "TreeNode", q: "TreeNode"
) -> "TreeNode":
cur = root
while cur:
if p.val < cur.val and q.val < cur.val:
cur = cur.left
elif p.val > cur.val and q.val > cur.val:
cur = cur.right
else:
return cur
```
@@ -0,0 +1,46 @@
---
title: '98. Validate Binary Search Tree'
description: Given the root of a binary tree, determine if it is a valid binary search tree (BST)
sidebar:
label: 'Validate Binary Search Tree'
badge: 'Medium'
---
<Badge variant="accent">Binary Search Tree</Badge>
### Example 1:
- Input: `root = [2,1,3]`
- Output: `true`
### Example 2:
- Input: `root = [5,1,4,null,null,3,6]`
- Output: `false`
- Explanation: The `root` node's value is `5` but its right child's value is `4`.
### Constraints:
- The number of nodes in the tree is in the range [1, 10^4].
- `-2^31 <= Node.val <= 2^31 - 1`
## Solution
```py
# 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 isValidBST(self, root: Optional[TreeNode]) -> bool:
def valid(node, low, high):
if not node:
return True
if not (low < node.val < high):
return False
return valid(node.left, low, node.val) and valid(node.right, node.val, high)
return valid(root, float("-inf"), float("inf"))
```
+5 -6
View File
@@ -1,12 +1,11 @@
--- ---
title: Introduction title: Overview
description: Welcome to your new Blume docs. description: Live SRS campaign dashboard — phases, ladder, review queue, gates, and recent attempts, fetched from the SRS Worker.
--- ---
## Getting Started
![Dependency Map](../public/dependency-spine.svg) ![Dependency Map](../public/dependency-spine.svg)
Welcome to **Blume** — markdown-first docs powered by Astro and Vite. Live view of the 56-day campaign. Everything below is fetched client-side
from the SRS Worker, so it is always current — no rebuild required.
Edit `docs/index.mdx` to get started, then run `blume dev`. <ProgressDashboard />
-9
View File
@@ -1,9 +0,0 @@
---
title: Progress
description: Live SRS campaign dashboard — phases, ladder, review queue, gates, and recent attempts, fetched from the SRS Worker.
---
Live view of the 56-day campaign. Everything below is fetched client-side
from the SRS Worker, so it is always current — no rebuild required.
<ProgressDashboard />
+4
View File
@@ -1,3 +1,7 @@
---
hidden: true
---
# todo — draining the review backlog # todo — draining the review backlog
every solution in `work/1` owes a blind re-solve at `work/3` and a second one at `work/7`. both buckets are empty, so 36 problems owe 72 re-solves and not one has been started. snapshot: `reviewqueues("2026-08-31")` from `apps/cli/work.ts` — what `bun run pick` shows — cross-checked against `/api/stats`. every solution in `work/1` owes a blind re-solve at `work/3` and a second one at `work/7`. both buckets are empty, so 36 problems owe 72 re-solves and not one has been started. snapshot: `reviewqueues("2026-08-31")` from `apps/cli/work.ts` — what `bun run pick` shows — cross-checked against `/api/stats`.
@@ -0,0 +1,51 @@
"""
217. Contains Duplicate
Difficulty: Easy
https://leetcode.com/problems/contains-duplicate/
──────────────────────────────────────────────────
Given an integer array nums, return true if any value appears at
least twice in the array, and return false if every element is
distinct.
Example 1:
Input: nums = [1,2,3,1]
Output: true
Explanation:
The element 1 occurs at the indices 0 and 3.
Example 2:
Input: nums = [1,2,3,4]
Output: false
Explanation:
All elements are distinct.
Example 3:
Input: nums = [1,1,1,3,3,4,3,2,4,2]
Output: true
Constraints:
• 1 <= nums.length <= 10^5
• -10^9 <= nums[i] <= 10^9
"""
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
@@ -0,0 +1,87 @@
"""
23. Merge k Sorted Lists
Difficulty: Hard
https://leetcode.com/problems/merge-k-sorted-lists/
──────────────────────────────────────────────────
You are given an array of k linked-lists lists, each linked-list is
sorted in ascending order.
Merge all the linked-lists into one sorted linked-list and return it.
Example 1:
Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
1->4->5,
1->3->4,
2->6
]
merging them into one sorted linked list:
1->1->2->3->4->4->5->6
Example 2:
Input: lists = []
Output: []
Example 3:
Input: lists = [[]]
Output: []
Constraints:
• k == lists.length
• 0 <= k <= 10^4
• 0 <= lists[i].length <= 500
• -10^4 <= lists[i][j] <= 10^4
• lists[i] is sorted in ascending order.
• The sum of lists[i].length will not exceed 10^4.
"""
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
import heapq
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
heap = []
# K log K
for i, node in enumerate(lists):
if node:
heapq.heappush(heap, (node.val, i, node))
D = ListNode()
cur = D
# n log k
while heap:
val, i, node = heapq.heappop(heap)
cur.next = node
cur = node
node = node.next
if node:
heapq.heappush(heap, (node.val, i, node))
# Time: O(N log k)
# Space: O(n)
return D.next
@@ -0,0 +1,50 @@
"""
215. Kth Largest Element in an Array
Difficulty: Medium
https://leetcode.com/problems/kth-largest-element-in-an-array/
──────────────────────────────────────────────────
Given an integer array nums and an integer k, return the k^th largest
element in the array.
Note that it is the k^th largest element in the sorted order, not the
k^th distinct element.
Can you solve it without sorting?
Example 1:
Input: nums = [3,2,1,5,6,4], k = 2
Output: 5
Example 2:
Input: nums = [3,2,3,1,2,4,5,5,6], k = 4
Output: 4
Constraints:
• 1 <= k <= nums.length <= 10^5
• -10^4 <= nums[i] <= 10^4
"""
import heapq
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
for i in range(len(nums)):
nums[i] = -nums[i]
heapq.heapify(nums)
for _ in range(k - 1):
heapq.heappop(nums)
return -heapq.heappop(nums)
@@ -0,0 +1,92 @@
"""
271. Encode and Decode Strings
Difficulty: Medium
https://leetcode.com/problems/encode-and-decode-strings/
──────────────────────────────────────────────────
Design an algorithm to encode a list of strings to a string. The
encoded string is then sent over the network and is decoded back to
the original list of strings.
Machine 1 (sender) has the function:
string encode(vector<string> strs) {
// ... your code
return encoded_string;
}
Machine 2 (receiver) has the function:
vector<string> decode(string s) {
//... your code
return strs;
}
So Machine 1 does:
string encoded_string = encode(strs);
and Machine 2 does:
vector<string> strs2 = decode(encoded_string);
strs2 in Machine 2 should be the same as strs in Machine 1.
Implement the encode and decode methods.
You are not allowed to solve the problem using any serialize methods
(such as eval).
Example 1:
Input: dummy_input = ["Hello","World"]
Output: ["Hello","World"]
Explanation:
Machine 1:
Codec encoder = new Codec();
String msg = encoder.encode(strs);
Machine 1 ---msg---> Machine 2
Machine 2:
Codec decoder = new Codec();
String[] strs = decoder.decode(msg);
Example 2:
Input: dummy_input = [""]
Output: [""]
Constraints:
• 1 <= strs.length <= 200
• 0 <= strs[i].length <= 200
• strs[i] contains any possible characters out of 256 valid ASCII
characters.
Follow up: Could you write a generalized algorithm to work on any
possible set of characters?
"""
class Codec:
def encode(self, strs: List[str]) -> str:
"""Encodes a list of strings to a single string.
"""
def decode(self, s: str) -> List[str]:
"""Decodes a single string to a list of strings.
"""
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(strs))
@@ -0,0 +1,64 @@
"""
973. K Closest Points to Origin
Difficulty: Medium
https://leetcode.com/problems/k-closest-points-to-origin/
──────────────────────────────────────────────────
Given an array of points where points[i] = [xi, yi] represents a
point on the X-Y plane and an integer k, return the k closest points
to the origin (0, 0).
The distance between two points on the X-Y plane is the Euclidean
distance (i.e., &radic;(x1 - x2)^2 + (y1 - y2)^2).
You may return the answer in any order. The answer is guaranteed to
be unique (except for the order that it is in).
Example 1:
Input: points = [[1,3],[-2,2]], k = 1
Output: [[-2,2]]
Explanation:
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest k = 1 points from the origin, so the answer
is just [[-2,2]].
Example 2:
Input: points = [[3,3],[5,-1],[-2,4]], k = 2
Output: [[3,3],[-2,4]]
Explanation: The answer [[-2,4],[3,3]] would also be accepted.
Constraints:
• 1 <= k <= points.length <= 10^4
• -10^4 <= xi, yi <= 10^4
"""
import heapq
class Solution:
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
minHeap = []
for x, y in points:
dist = (x**2) + (y**2)
minHeap.append([dist, x, y])
heapq.heapify(minHeap)
res = []
while k > 0:
dist, x, y = heapq.heappop(minHeap)
res.append([x, y])
k -= 1
return res
@@ -0,0 +1,63 @@
"""
230. Kth Smallest Element in a BST
Difficulty: Medium
https://leetcode.com/problems/kth-smallest-element-in-a-bst/
──────────────────────────────────────────────────
Given the root of a binary search tree, and an integer k, return the
k^th smallest value (1-indexed) of all the values of the nodes in the
tree.
Example 1:
Input: root = [3,1,4,null,2], k = 1
Output: 1
Example 2:
Input: root = [5,3,6,2,4,null,null,1], k = 3
Output: 3
Constraints:
• The number of nodes in the tree is n.
• 1 <= k <= n <= 10^4
• 0 <= Node.val <= 10^4
Follow up: If the BST is modified often (i.e., we can do insert and
delete operations) and you need to find the kth smallest frequently,
how would you optimize?
"""
# 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
n = 0
stack = []
cur = root
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
cur = stack.pop()
n += 1
if n == k:
return cur.val
cur = cur.right
@@ -0,0 +1,70 @@
"""
235. Lowest Common Ancestor of a Binary Search Tree
Difficulty: Medium
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
──────────────────────────────────────────────────
Given a binary search tree (BST), find the lowest common ancestor
(LCA) node of two given nodes in the BST.
According to the definition of LCA on Wikipedia: &ldquo;The lowest
common ancestor is defined between two nodes p and q as the lowest
node in T that has both p and q as descendants (where we allow a node
to be a descendant of itself).&rdquo;
Example 1:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation: The LCA of nodes 2 and 8 is 6.
Example 2:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a
descendant of itself according to the LCA definition.
Example 3:
Input: root = [2,1], p = 2, q = 1
Output: 2
Constraints:
• The number of nodes in the tree is in the range [2, 10^5].
• -10^9 <= Node.val <= 10^9
• All Node.val are unique.
• p != q
• p and q will exist in the BST.
"""
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(
self, root: "TreeNode", p: "TreeNode", q: "TreeNode"
) -> "TreeNode":
cur = root
while cur:
if p.val < cur.val and q.val < cur.val:
cur = cur.left
elif p.val > cur.val and q.val > cur.val:
cur = cur.right
else:
return cur
@@ -0,0 +1,62 @@
"""
98. Validate Binary Search Tree
Difficulty: Medium
https://leetcode.com/problems/validate-binary-search-tree/
──────────────────────────────────────────────────
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 strictly
less than the node's key.
• The right subtree of a node contains only nodes with keys strictly
greater than the node's key.
• Both the left and right subtrees must also be binary search trees.
Example 1:
Input: root = [2,1,3]
Output: true
Example 2:
Input: root = [5,1,4,null,null,3,6]
Output: false
Explanation: The root node's value is 5 but its right child's value
is 4.
Constraints:
• The number of nodes in the tree is in the range [1, 10^4].
• -2^31 <= Node.val <= 2^31 - 1
"""
# 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 isValidBST(self, root: Optional[TreeNode]) -> bool:
def valid(node, low, high):
if not node:
return True
if not (low < node.val < high):
return False
return valid(node.left, low, node.val) and valid(node.right, node.val, high)
return valid(root, float("-inf"), float("inf"))