From cc4144220b823dc1d9b9565be2c6e5424a33536b Mon Sep 17 00:00:00 2001 From: rishigoswamy Date: Sun, 15 Mar 2026 12:27:32 -0700 Subject: [PATCH] Add implementation for leetcode problems 113, 101 --- leetcode_101.py | 118 ++++++++++++++++++++++++++++++++++++++++ leetcode_113.py | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 leetcode_101.py create mode 100644 leetcode_113.py diff --git a/leetcode_101.py b/leetcode_101.py new file mode 100644 index 00000000..f654e3e7 --- /dev/null +++ b/leetcode_101.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sun Mar 15 00:00:00 2026 + +@author: rishigoswamy + + LeetCode 101: Symmetric Tree + Link: https://leetcode.com/problems/symmetric-tree/ + + Problem: + Given the root of a binary tree, check whether it is a mirror of itself + (i.e., symmetric around its center). + + Approach: + BFS using a deque. Push the root twice to seed the comparison. + At each step, pop two nodes (left and right mirrors) and compare their values. + Then enqueue their children in mirror order: + - left.left paired with right.right (outer pair) + - left.right paired with right.left (inner pair) + + 1️⃣ Seed queue with root twice. + 2️⃣ Pop two nodes at a time; if both None → continue; one None or values differ → False. + 3️⃣ Enqueue outer pair (left.left, right.right) then inner pair (left.right, right.left). + 4️⃣ If queue empties without returning False → return True. + + // Time Complexity : O(n) + Every node is visited once. + // Space Complexity : O(n) + Queue holds at most O(n) nodes at a level. + +""" + +from collections import deque +from typing import Optional + +# 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 isSymmetric(self, root: Optional[TreeNode]) -> bool: + # Keep left child of left parent and right child of right parent together in queue + # Keep right child of left parent and left child of right parent together in queue + queue = deque() + queue.append(root) + queue.append(root) + + while queue: + left = queue.popleft() + right = queue.popleft() + if left is None and right is None: + continue + elif left is None or right is None: + return False + elif left.val != right.val: + return False + + queue.append(left.left) + queue.append(right.right) + queue.append(left.right) + queue.append(right.left) + + return True + + ''' + def isSymmetric(self, root: Optional[TreeNode]) -> bool: + # Using queue, add left and right child even if they are null. At for each node check if it + # is not null only then add child. + queue = deque() + queue.append(root) + + while queue: + size = len(queue) + level = [] + for i in range(size): + node = queue.popleft() + level.append(node) + + if node: + queue.append(node.left) + queue.append(node.right) + l = 0 + r = len(level) - 1 + while l < r: + left = level[l] + right = level[r] + if left is None and right is None: + l += 1 + r -= 1 + continue + elif left is None or right is None: + return False + elif left.val != right.val: + return False + l += 1 + r -= 1 + return True + ''' + + ''' + def isSymmetric(self, root: Optional[TreeNode]) -> bool: + def dfs(left, right): + if left is None and right is None: + return True + elif left is None or right is None: + return False + elif left.val != right.val: + return False + # returning by this way reduces operations because as soon as it sees + # false in any of the sides it will return False + return dfs(left.left, right.right) and dfs(left.right, right.left) + + return dfs(root, root) + ''' diff --git a/leetcode_113.py b/leetcode_113.py new file mode 100644 index 00000000..01ca89eb --- /dev/null +++ b/leetcode_113.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sun Mar 15 00:00:00 2026 + +@author: rishigoswamy + + LeetCode 113: Path Sum II + Link: https://leetcode.com/problems/path-sum-ii/ + + Problem: + Given the root of a binary tree and an integer targetSum, return all root-to-leaf + paths where the sum of the node values equals targetSum. Each path should be + returned as a list of node values. + + Approach: + DFS with backtracking. Maintain a running array and currSum as we recurse. + At each leaf, check if currSum == targetSum and append a copy of array to results. + Backtrack by popping the last element from array on return. + + 1️⃣ Append current node's value to array; add to currSum. + 2️⃣ At a leaf, if currSum == targetSum → append array.copy() to self.res. + 3️⃣ Recurse left and right subtrees. + 4️⃣ Backtrack: pop last element from array before returning. + + // Time Complexity : O(n) + Every node is visited once. + // Space Complexity : O(h) + Recursive call stack depth equals the height of the tree. + The array at any point holds at most h elements. + +""" + +from typing import List, Optional + +# 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 pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]: + def traversal(root, array, currSum): + if not root: + return + + array.append(root.val) + currSum += root.val + if not root.left and not root.right: + if currSum == targetSum: + self.res.append(array.copy()) + traversal(root.left, array, currSum) + traversal(root.right, array, currSum) + + array.pop() + + self.res = [] + traversal(root, [], 0) + return self.res + + ''' + def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]: + def traversal(root, array): + if not root: + return + + array.append(root.val) + currSum = sum(array) + if not root.left and not root.right: + if currSum == targetSum: + self.res.append(array.copy()) + traversal(root.left, array) + traversal(root.right, array) + + array.pop() + + self.res = [] + traversal(root, []) + return self.res + ''' + + ''' + def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]: + def traversal(root, array, currSum): + if not root: + return + + array.append(root.val) + tempLeft = [] + for item in array: + tempLeft.append(item) + tempRight = [] + for item in array: + tempRight.append(item) + currSum += root.val + if not root.left and not root.right: + if currSum == targetSum: + self.res.append(array) + traversal(root.left, tempLeft, currSum) + traversal(root.right, tempRight, currSum) + + self.res = [] + traversal(root, [], 0) + return self.res + ''' + + ''' + def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]: + if not root: + return [] + + queue = [] + queue.append([root, root.val, [root.val]]) + res = [] + + while queue: + node, currSum, path = queue.pop(0) + if node.left: + temp = [] + for item in path: + temp.append(item) + temp.append(node.left.val) + queue.append([node.left, currSum + node.left.val, temp]) + + if node.right: + temp = [] + for item in path: + temp.append(item) + temp.append(node.right.val) + queue.append([node.right, currSum + node.right.val, temp]) + + if not node.left and not node.right: + if currSum == targetSum: + res.append(path) + + return res + '''