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
29 changes: 29 additions & 0 deletions Problem1_1D_array_approach.py
Original file line number Diff line number Diff line change
@@ -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]
44 changes: 44 additions & 0 deletions Problem1_BFS.py
Original file line number Diff line number Diff line change
@@ -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
53 changes: 53 additions & 0 deletions Problem1_BFS_Deque.py
Original file line number Diff line number Diff line change
@@ -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
33 changes: 33 additions & 0 deletions Problem1_exhaustive_approach.py
Original file line number Diff line number Diff line change
@@ -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
37 changes: 37 additions & 0 deletions Problem1_memo_approach.py
Original file line number Diff line number Diff line change
@@ -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]
29 changes: 29 additions & 0 deletions Problem1_tabular_approach.py
Original file line number Diff line number Diff line change
@@ -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]
36 changes: 36 additions & 0 deletions Problem2_Course_Schedule.py
Original file line number Diff line number Diff line change
@@ -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
39 changes: 39 additions & 0 deletions Problem2_paint_house_naive.py
Original file line number Diff line number Diff line change
@@ -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()
23 changes: 23 additions & 0 deletions Problem2_paint_house_space_optimal_Sol.py
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions Problem2_paint_house_tabular_bottom_up.py
Original file line number Diff line number Diff line change
@@ -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

18 changes: 18 additions & 0 deletions Problem2_paint_house_tabular_top_down.py
Original file line number Diff line number Diff line change
@@ -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