From e06b12d5919c2e4f2c19a90ecd360f3cefdc03b1 Mon Sep 17 00:00:00 2001 From: Manasvi Reddy Date: Sun, 5 Jul 2026 22:50:20 -0400 Subject: [PATCH] Done Trees-1 --- Problem1.py | 39 +++++++++++++++++++++++++++++++++++++++ Problem2.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 Problem1.py create mode 100644 Problem2.py diff --git a/Problem1.py b/Problem1.py new file mode 100644 index 00000000..bf7f9b16 --- /dev/null +++ b/Problem1.py @@ -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 \ No newline at end of file diff --git a/Problem2.py b/Problem2.py new file mode 100644 index 00000000..21156aa9 --- /dev/null +++ b/Problem2.py @@ -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 + \ No newline at end of file