From 512e6bf5c9331ba0fb0ed00ab8fa35d3e39ba49a Mon Sep 17 00:00:00 2001 From: Sanket Kale Date: Sat, 27 Jun 2026 21:11:51 -0500 Subject: [PATCH 1/2] Completed Trees-2 --- Problem1.py | 1 + Problem2.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 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..c4ec3bd3 --- /dev/null +++ b/Problem1.py @@ -0,0 +1 @@ +## Problem1 (https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/) \ No newline at end of file diff --git a/Problem2.py b/Problem2.py new file mode 100644 index 00000000..18ca536d --- /dev/null +++ b/Problem2.py @@ -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 \ No newline at end of file From 83ce903820c48d1d1ed01d325583a55e8b7f5867 Mon Sep 17 00:00:00 2001 From: Sanket Kale Date: Sat, 27 Jun 2026 21:32:53 -0500 Subject: [PATCH 2/2] Completed Trees-2. --- Problem1.py | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- Problem2.py | 2 +- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Problem1.py b/Problem1.py index c4ec3bd3..5d2f2397 100644 --- a/Problem1.py +++ b/Problem1.py @@ -1 +1,48 @@ -## Problem1 (https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/) \ No newline at end of file +## 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 \ No newline at end of file diff --git a/Problem2.py b/Problem2.py index 18ca536d..184a2a23 100644 --- a/Problem2.py +++ b/Problem2.py @@ -44,7 +44,7 @@ def helper(node, current): helper(node.left, current) helper(node.right, current) - # Initialize the DFS traversal starting at the root with a current value of 0 + # Initialize the DFS traversal starting at the root with a current value of 0. helper(root, 0) return result \ No newline at end of file