From 678add8d415031280bca4b07e937ed9ef403cd9c Mon Sep 17 00:00:00 2001 From: Manasvi Reddy Date: Sun, 5 Jul 2026 19:46:01 -0400 Subject: [PATCH] Done Trees-2 --- Problem1.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ Problem2.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 86 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..894d8ffd --- /dev/null +++ b/Problem1.py @@ -0,0 +1,51 @@ +# Problem1 (https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-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 last value in postorder is always the root of the current subtree so we read it using a pointer that moves backward +# 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 right subtree before the left subtree because reading postorder backward gives root then right side then left 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, inorder: List[int], postorder: 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 last index of postorder and will move backward as we build each root + self.postorder_index = len(postorder)-1 + + # 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(postorder,0,len(inorder)-1) + + def helper(self,postorder,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 postorder is always the root of this subtree + root_value = postorder[self.postorder_index] + + # 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] + + # move the pointer one step back so the next call reads the correct next value + self.postorder_index -=1 + + # create the node for this root value + node = TreeNode(root_value) + + # build the right subtree first since reading postorder backward gives right side nodes before left side nodes + node.right = self.helper(postorder,root_index+1, end) + # only after the right subtree is fully built do we build the left subtree + node.left = self.helper(postorder,start, root_index -1) + + return node \ No newline at end of file diff --git a/Problem2.py b/Problem2.py new file mode 100644 index 00000000..87824722 --- /dev/null +++ b/Problem2.py @@ -0,0 +1,35 @@ +# Problem2 (https://leetcode.com/problems/sum-root-to-leaf-numbers/) +# Time Complexity: O(n), we visit every node exactly once +# Space Complexity: O(h), h is the height of the tree, this space comes from the recursion call stack + +# Approach: We walk down the tree from root to leaf using recursion. +# As we move to each node, we build a number by taking the number built so far, multiplying it by 10, then adding the current node's value. +# When we reach a leaf node, the number is complete, so we add it to a running total. +# We keep doing this for every path in the tree until all leaves are visited, then return the total. + +# 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 sumNumbers(self, root: Optional[TreeNode]) -> int: + self.result = 0 # this will hold the total sum of all root to leaf numbers, starts at 0 since nothing is added yet + self.helper(root, 0) # start the recursion at the root, with current_number as 0 since nothing has been built yet + return self.result + + def helper(self, root, current_number): + if root is None: # if we have gone past a leaf, there is nothing to do here + return + + current_number = current_number * 10 + root.val + # shift the digits built so far one place to the left, then add the current node's value this is how numbers are built digit by digit. + if root.left is None and root.right is None: # this means the current node is a leaf, no children on either side + self.result += current_number + # since this is a leaf, current_number is now a complete root to leaf number, so we add it to the total + + self.helper(root.left, current_number) + # move to the left child, carrying forward the number built so far so it can keep building on it + self.helper(root.right, current_number) + # move to the right child, carrying forward the same number built so far, independent of what the left side does \ No newline at end of file