From a3f03ffe7dcf2697b1e5f2778f70e5d9774ac223 Mon Sep 17 00:00:00 2001 From: Srijha-Kalyan <87617310+Srijha-Kalyan@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:27:37 -0500 Subject: [PATCH 1/2] Add files via upload --- Problem1_1D_array_approach.py | 29 +++++++++++++++++ Problem1_exhaustive_approach.py | 33 +++++++++++++++++++ Problem1_memo_approach.py | 37 +++++++++++++++++++++ Problem1_tabular_approach.py | 29 +++++++++++++++++ Problem2_paint_house_naive.py | 39 +++++++++++++++++++++++ Problem2_paint_house_space_optimal_Sol.py | 23 +++++++++++++ Problem2_paint_house_tabular_bottom_up.py | 18 +++++++++++ Problem2_paint_house_tabular_top_down.py | 18 +++++++++++ 8 files changed, 226 insertions(+) create mode 100644 Problem1_1D_array_approach.py create mode 100644 Problem1_exhaustive_approach.py create mode 100644 Problem1_memo_approach.py create mode 100644 Problem1_tabular_approach.py create mode 100644 Problem2_paint_house_naive.py create mode 100644 Problem2_paint_house_space_optimal_Sol.py create mode 100644 Problem2_paint_house_tabular_bottom_up.py create mode 100644 Problem2_paint_house_tabular_top_down.py diff --git a/Problem1_1D_array_approach.py b/Problem1_1D_array_approach.py new file mode 100644 index 00000000..e96e67f3 --- /dev/null +++ b/Problem1_1D_array_approach.py @@ -0,0 +1,29 @@ +class Solution(object): + def coinChange(self, coins, amount): + """ + There are two choices here: either not choosing a coin or choosing a coin and adding 1 to it + Time complexity O(m*n), space complexity: O(n) where m is length of coin array and n is amount + :type coins: List[int] + :type amount: int + :rtype: int + """ + m = len(coins) + n = amount + + dp = [99999 * (n+1)] + dp[0] = 0 + + for j in range(1, m+1): + dp[j] = -1 + + for coin in coins: + for j in range(1, m+1): + if j < coin: + dp[j] = dp[j] + else: + dp[j] = dp[j] + dp[j - coin]+1 + + if dp[n]==99999: + return -1 + else: + return dp[n] \ No newline at end of file diff --git a/Problem1_exhaustive_approach.py b/Problem1_exhaustive_approach.py new file mode 100644 index 00000000..5a1c5500 --- /dev/null +++ b/Problem1_exhaustive_approach.py @@ -0,0 +1,33 @@ +import sys +class Solution(object): + def coinChange(self, coins, amount): + """ + The exhaustive approach takes the addition of all possible combinations + Time complexity: 2^(n*m) n is length of coin array and m is amount + :type coins: List[int] + :type amount: int + :rtype: int + """ + re = self.helper(coins, amount, 0) + #coins = [2], amount = 3 you can make any amount give here, + # if ive gone out of bounds + if re >= sys.maxsize: + return -1 + return re + + def helper(self, coins, amount, idx): + #base case + if (amount==0): + return 0 + #the amount becomes negative — this path is invalid + if amount < 0 or idx == len(coins): + return sys.maxsize + + #logic + #case 1 - dont choose + case1 = self.helper(coins, amount, idx+1) + #case2 - choose + #add +1 because I just chose that one coin in the current index + case2 = 1 + self.helper(coins, amount-coins[idx], idx) + + return case1 + case2 \ No newline at end of file diff --git a/Problem1_memo_approach.py b/Problem1_memo_approach.py new file mode 100644 index 00000000..07c5637c --- /dev/null +++ b/Problem1_memo_approach.py @@ -0,0 +1,37 @@ +class Solution(object): + def coinChange(self, coins, amount): + """ + Time complexity O(m*n), Space: O(m*n) where m is length of coin array and n is amount + :type coins: List[int] + :type amount: int + :rtype: int + """ + re = self.helper(coins, amount, 0) + #coins = [2], amount = 3 you can make any amount give here, + # if ive gone out of bounds + m = len(coins) + n = amount + self.memo = [[0] * (n + 1) for _ in range(m + 1)] + if re >= 99999: + return -1 + return re + + def helper(self, coins, amount, idx): + #base case + if (amount==0): + return 0 + #the amount becomes negative — this path is invalid + if amount < 0 or idx == len(coins): + return 99999 + + if self.memo[idx][amount] != 0: + return self.memo[idx][amount] + #logic + #case 1 - dont choose + case1 = self.helper(coins, amount, idx+1) + #case2 - choose + #add +1 because I just chose that one coin in the current index + case2 = 1 + self.helper(coins, amount-coins[idx], idx) + + self.memo[idx][amount] = case1 + case2 + return self.memo[idx][amount] \ No newline at end of file diff --git a/Problem1_tabular_approach.py b/Problem1_tabular_approach.py new file mode 100644 index 00000000..7024fe68 --- /dev/null +++ b/Problem1_tabular_approach.py @@ -0,0 +1,29 @@ +class Solution(object): + def coinChange(self, coins, amount): + """ + There are two choices here: either not choosing a coin or choosing a coin and adding 1 to it + Time complexity O(m*n), space complexity: O(m*n) where m is length of coin array and n is amount + :type coins: List[int] + :type amount: int + :rtype: int + """ + m = len(coins) + n = amount + + dp = [[0] * (n+1) for _ in range(m+1)] + + + for j in range(1, m+1): + dp[0][j] = -1 + + for i in range(1, n+1): + for j in range(1, m+1): + if j < coins[i-1]: + dp[i][j] = dp[i-1][j] + else: + dp[i][j] = dp[i-1][j] + dp[i][j - coins[i-1]]+1 + + if dp[m][n]==99999: + return -1 + else: + return dp[m][n] \ No newline at end of file diff --git a/Problem2_paint_house_naive.py b/Problem2_paint_house_naive.py new file mode 100644 index 00000000..da50a9eb --- /dev/null +++ b/Problem2_paint_house_naive.py @@ -0,0 +1,39 @@ +class Solution: + #exhaustive approach of trying out all possibilities and the time complexity + # is m*2^n where m is number of colors + def minCost(self, costs): # 0-R, 1-B, 2-G + colorR = self.helper(costs, 0, 0, 0) + colorB = self.helper(costs, 0, 1, 0) + colorG = self.helper(costs, 0, 2, 0) + #return the minimum cost out of all the 3 colors + return min(colorR, colorB, colorG) + + def helper(self, costs, i, color, totalCost): + #base + # If we’ve already painted all houses (index i has reached the end of the list), + # then there are no more recursive choices to make, + # so we just return the accumulated total cost. + if(i==len(costs)): + return totalCost + + #logic + #if color is Red + if(color == 0): + #2 possibilities + colorB = self.helper(costs, i+1, 1) + colorG = self.helper(costs, i+1, 2) + return costs[i][0] + min(colorB, colorG) + + #color is blue + elif(color == 1): + colorR = self.helper(costs, i+1, 0) + colorG = self.helper(costs, i+1, 2) + return costs[i][1] + min(colorR, colorG) + + #Green + elif(color == 2): + colorR = self.helper(costs, i+1, 0) + colorB = self.helper(costs, i+1, 1) + return costs[i][1] + min(colorR, colorB) + + return max.size() \ No newline at end of file diff --git a/Problem2_paint_house_space_optimal_Sol.py b/Problem2_paint_house_space_optimal_Sol.py new file mode 100644 index 00000000..7b6c9a7a --- /dev/null +++ b/Problem2_paint_house_space_optimal_Sol.py @@ -0,0 +1,23 @@ +class Solution: + #Time complexity O(n) Space is O(1) since variable stored in temp var + def minCost(self, costs): # 0-R, 1-B, 2-G + n = len(costs) #rows of houses + m = len(costs[0]) #cols of diff colors + dp = [[0] * n for _ in range(m)] + + colorR = costs[n-1][0] #starting bottom up last red house + colorB = costs[n-1][1] #last blue house + colorG = costs[n-1][2] #last green house + min(colorR, colorB, colorG) + + for i in range (n-2, -1, 1): + #WHENEVER YOU ARE MUTATING AN ORIGINAL VALUE STORE IT IN A TEMP ARRAY + #SO THAT ORGINAL VALUE CAN BE USED LATER + tempR = colorR + tempB = colorB + + colorR = costs[i][0] + min(colorB, colorG) # + colorB = costs[i][1] + min(tempR, colorG) #ORIGINAL DP[0] AKA COLORR + colorG = costs[i][2] + min(tempR, tempB) #ORIGINAL DP[1] AKA COLORB + re = min(dp[0][0], dp[0][1], dp[0][2]) + return re \ No newline at end of file diff --git a/Problem2_paint_house_tabular_bottom_up.py b/Problem2_paint_house_tabular_bottom_up.py new file mode 100644 index 00000000..6a402d7c --- /dev/null +++ b/Problem2_paint_house_tabular_bottom_up.py @@ -0,0 +1,18 @@ +class Solution: + #Time complexity O(n) + def minCost(self, costs): # 0-R, 1-B, 2-G + n = len(costs) #rows of houses + m = len(costs[0]) #cols of diff colors + dp = [[0] * n for _ in range(m)] + + dp[n-1][0] = costs[n-1][0] #starting bottom up last red house + dp[n-1][1] = costs[n-1][1] #last blue house + dp[n-1][2] = costs[n-1][2] #last green house + + for i in range (n-2, -1, 1): + dp[i][0] = costs[i][0] + min(dp[i+1][1], dp[i+1][2]) # + dp[i][1] = costs[i][1] + min(dp[i+1][0], dp[i+1][2]) + dp[i][2] = costs[i][2] + min(dp[i+1][0], dp[i+1][1]) + re = min(dp[0][0], dp[0][1], dp[0][2]) + return re + diff --git a/Problem2_paint_house_tabular_top_down.py b/Problem2_paint_house_tabular_top_down.py new file mode 100644 index 00000000..1f922251 --- /dev/null +++ b/Problem2_paint_house_tabular_top_down.py @@ -0,0 +1,18 @@ +class Solution: + #Time complexity O(n) + def minCost(self, costs): # 0-R, 1-B, 2-G + n = len(costs) #rows of houses + m = len(costs[0]) #cols of diff colors + dp = [[0] * n for _ in range(m)] + + dp[0][0] = costs[0][0] #starting bottom up last red house + dp[1][1] = costs[1][1] #last blue house + dp[2][2] = costs[2][2] #last green house + + for i in range (1, n): + dp[i][0] = costs[i][0] + min(dp[i-1][1], dp[i-1][2]) # + dp[i][1] = costs[i][1] + min(dp[i-1][0], dp[i-1][2]) + dp[i][2] = costs[i][2] + min(dp[i-1][0], dp[i-1][1]) + re = min(dp[n-1][0], dp[n-1][1], dp[n-1][2]) + return re + From 31c73cdc813d177e33755e892d051bd9f51e7796 Mon Sep 17 00:00:00 2001 From: Srijha-Kalyan <87617310+Srijha-Kalyan@users.noreply.github.com> Date: Mon, 17 Nov 2025 19:43:09 -0500 Subject: [PATCH 2/2] Add files via upload --- Problem1_BFS.py | 44 ++++++++++++++++++++++++++++++ Problem1_BFS_Deque.py | 53 +++++++++++++++++++++++++++++++++++++ Problem2_Course_Schedule.py | 36 +++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 Problem1_BFS.py create mode 100644 Problem1_BFS_Deque.py create mode 100644 Problem2_Course_Schedule.py diff --git a/Problem1_BFS.py b/Problem1_BFS.py new file mode 100644 index 00000000..e1754913 --- /dev/null +++ b/Problem1_BFS.py @@ -0,0 +1,44 @@ +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution(object): + def levelOrder(self, root): + """ + :type root: Optional[TreeNode] + :rtype: List[List[int]] + + 1 + 2 3 + 4 5 6 7 + o/p: + [ + [1], + [2,3], + [4,5,6,7] + ] + We need to keep track of level list and rsult adds the lists + queue takes root and next_queue adds left and right children + Time complexity:O(N) + Space Complexity: O(h) where h is height of tree + """ + if root is None: + return [] + queue = [root] + level = [] + result = [] + + while queue!=[]: + for root in queue: + level.append(root.val) + if root.left is not None: + next_queue.append(root.left) + if root.right is not None: + next_queue.append(root.right) + result.append(level) + level = [] + queue = next_queue + next_queue = [] + return result diff --git a/Problem1_BFS_Deque.py b/Problem1_BFS_Deque.py new file mode 100644 index 00000000..290b58a7 --- /dev/null +++ b/Problem1_BFS_Deque.py @@ -0,0 +1,53 @@ +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +# Definition for a binary tree node. +# class TreeNode(object): +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = rig +from collections import deque +class Solution(object): + def levelOrder(self, root): + """ + :type root: Optional[TreeNode] + :rtype: List[List[int]] + + 1 + 2 3 + 4 5 6 7 + o/p: + [ + [1], + [2,3], + [4,5,6,7] + ] + We need to keep track of level list and rsult adds the lists + queue takes root and next_queue adds left and right children + Time complexity:O(N) + Space Complexity: O(h) where h is height of tree + """ + if root is None: + return [] + queue = deque([root]) + level = 0 + level_list = [] + result = [] + + while queue: + for _ in range(len(queue)): + curr_root = queue.popleft() + level_list.append(curr_root.val) + print(level_list) + if curr_root.left is not None: + queue.append(curr_root.left) + if curr_root.right is not None: + queue.append(curr_root.right) + result.append(level_list) + level+=1 + level_list = [] + return result diff --git a/Problem2_Course_Schedule.py b/Problem2_Course_Schedule.py new file mode 100644 index 00000000..6608affe --- /dev/null +++ b/Problem2_Course_Schedule.py @@ -0,0 +1,36 @@ +from collections import defaultdict +class Solution(object): + def canFinish(self, numCourses, prerequisites): + """ + The idea is to return false when a cycle is detected + add the couese number in key and list as values + Time complexity: O(P+C) where C is number of courses and P is number of edges(prerequisites) + Space Complexity: O(P+C) for the hashtable + :type numCourses: int + :type prerequisites: List[List[int]] + :rtype: bool + """ + prereqs = defaultdict(list) + #add the courses and prereqs in this hastable + for c, p in prerequisites: + prereqs[c].append(p) + + seen = set() + + def cycle(course, seen): + if course in seen: + return True + + seen.add(course) + for p in prereqs[course]: + if cycle(p, seen): + return True + prereqs[course] = [] + seen.remove(course) + return False + + + for course in range(numCourses): + if cycle(course, seen): + return False + return True \ No newline at end of file