Skip to content
Open
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
39 changes: 39 additions & 0 deletions Problem1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#https://leetcode.com/problems/validate-binary-search-tree/
# Time Complexity: O(n), we visit every node exactly once
# Space Complexity: O(h), h is the height of the tree, due to recursion stack
# Approach: do an in-order traversal (left, current, right).
#In a valid BST, this visits values in strictly increasing order, so we just compare each node to the one visited right before it.

# 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:


self.flag = True # assume valid until we find proof otherwise
self.prev = None # tracks the previously visited node in the in-order walk

def helper(currentNode):
# base case: we've gone past a leaf, nothing here to check
if currentNode is None:
return

# step 1: fully process the entire left side first
helper(currentNode.left)

# step 2: now check the current node against the last one we visited
if self.prev is not None and self.prev.val >= currentNode.val:
self.flag = False

# step 3: this node is now "the previous one" for whatever comes next
self.prev = currentNode

# step 4: now process the entire right side
helper(currentNode.right)

helper(root) # kick off the traversal starting at the actual tree root
return self.flag # report whether any violation was found
53 changes: 53 additions & 0 deletions Problem2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
# Time Complexity: O(n), We visit every node exactly once and each visit does constant work using dictionary lookup and a moving pointer
# Space Complexity: O(n), We use a dictionary of size n to store index positions and the recursion stack can go up to depth n in the worst case
# Approach: The first value in preorder is always the root of the current subtree so we read it using a pointer that moves forward
# We use a dictionary to instantly find where that root sits in inorder so we know how many nodes go to the left and right
# We always build the left subtree before the right subtree because reading preorder forward gives root then left side then right side

# 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
# this dictionary will store the index of every value in inorder so we never have to search for it later
self.map = {}

# this pointer starts at the first index of preorder and will move forward as we build each root
self.preorder_index = 0

# fill the dictionary once so lookups later take constant time
for i in range(len(inorder)):
self.map[inorder[i]] = i

# start building the tree using the full range of inorder, from index 0 to the last index
return self.helper(preorder, 0, len(inorder) - 1)

def helper(self, preorder, start, end):
# if start has gone past end it means there are no elements left in this range so there is nothing to build
if start > end:
return None

# the value at our current pointer position in preorder is always the root of this subtree
root_value = preorder[self.preorder_index]

# move the pointer one step forward so the next call reads the correct next value
self.preorder_index += 1

# look up where this root value sits in inorder so we know how to split left and right parts
root_index = self.map[root_value]

# create the node for this root value
node = TreeNode(root_value)

# build the left subtree first since reading preorder forward gives left side nodes before right side nodes
node.left = self.helper(preorder, start, root_index - 1)
# only after the left subtree is fully built do we build the right subtree
node.right = self.helper(preorder, root_index + 1, end)

# return this node with both children attached back to whoever called this
return node