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
48 changes: 48 additions & 0 deletions Problem1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Problem1 (https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/)
# 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]:
"""
Time Complexity: O(N^2) in the worst case (e.g., a completely skewed tree).
At each level of the recursion, inorder.index() takes O(N) time to find the element,
and array slicing creates new lists which also takes O(N) time. Since this is done
for all N nodes, the worst-case time bounds to O(N^2). The average case for a
balanced tree is O(N log N).

Space Complexity: O(N^2) in the worst case.
The recursive call stack can go as deep as N levels in a skewed tree (O(N) space).
Additionally, the array slicing (inorder[:mid], postorder[:mid], etc.) creates copies
of the lists at each recursive step, resulting in O(N^2) extra space overhead.
"""

# Base case: if the arrays are empty, there are no nodes to construct for this subtree
if not inorder or not postorder:
return None

# Logic: In a postorder traversal (Left, Right, Root), the last element is ALWAYS
# the root of the current tree/subtree. We extract it to create our root node.
root = TreeNode(postorder[-1])

# Logic: In an inorder traversal (Left, Root, Right), the root splits the array.
# Everything to the left of the root's index belongs to the left subtree, and
# everything to the right belongs to the right subtree.
mid = inorder.index(postorder[-1])

# Recursively construct the left subtree:
# - Inorder left half: from start up to (but not including) the 'mid' index.
# - Postorder left half: the first 'mid' elements correspond to the left subtree's nodes.
root.left = self.buildTree(inorder[:mid], postorder[:mid])

# Recursively construct the right subtree:
# - Inorder right half: from 'mid + 1' to the end.
# - Postorder right half: from 'mid' up to the second-to-last element
# (since we exclude the very last element, which is the root we already processed).
root.right = self.buildTree(inorder[mid + 1:], postorder[mid:-1])

# Return the fully constructed root of the current subtree
return root
50 changes: 50 additions & 0 deletions Problem2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
## Problem2 (https://leetcode.com/problems/sum-root-to-leaf-numbers/)
# 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:
"""
Time Complexity: O(N)
- We visit every node in the binary tree exactly once during our Depth-First Search (DFS).

Space Complexity: O(H)
- H is the height of the tree, which represents the maximum depth of the recursion stack.
- In the worst-case scenario (a skewed tree), this is O(N).
- In the best-case scenario (a perfectly balanced tree), this is O(log N).
"""
result = 0

def helper(node, current):
nonlocal result

# Base case: if the current node is null, stop traversing this path
if node == None:
return

# LOGIC: Build the number sequentially as we traverse deeper.
# Shift the existing digits left (multiply by 10) and add the new digit.
# E.g., for a path [1, 2, 3]:
# Root (1): current = 0 * 10 + 1 = 1
# Child (2): current = 1 * 10 + 2 = 12
# Leaf (3): current = 12 * 10 + 3 = 123
current = 10 * current + node.val

# If both left and right children are None, we have reached a leaf node.
# This means our path is complete, so we add the path's total to our global result.
if node.left is None and node.right is None:
result += current

# Recursively call the helper on the left and right subtrees
# while passing down the current number formed so far.
helper(node.left, current)
helper(node.right, current)

# Initialize the DFS traversal starting at the root with a current value of 0.
helper(root, 0)

return result