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
51 changes: 51 additions & 0 deletions Problem1.py
Original file line number Diff line number Diff line change
@@ -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
35 changes: 35 additions & 0 deletions Problem2.py
Original file line number Diff line number Diff line change
@@ -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