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
59 changes: 59 additions & 0 deletions 256. Paint House.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# EXHAUSTIVE SOLUTION

# Time: O(2^n) n=> number of houses
# Space: O(n) As the recursion depth is only till the length of costs i.e the number of rows which determines the houses

# Loop through the number of colors
# check in the helper function which color we use and use the remaining colors
# Check whats the cost of minimum between the two colors and add the current cost in it
class Solution:
def minCost(self, costs: List[List[int]]) -> int:
min_val = float('inf')
for n in range(len(costs[0])):
min_val = min(min_val, self.helper(costs, 0, n))
return min_val

def helper(self, costs, idx, n):
# base
if idx == len(costs):
return 0

# Logic
if n == 0:
choose_blue = self.helper(costs, idx + 1, n + 1)
choose_green = self.helper(costs, idx + 1, n + 2)

return costs[idx][n] + min(choose_blue, choose_green)
elif n == 1:
choose_red = self.helper(costs, idx + 1, n - 1)
choose_green = self.helper(costs, idx + 1, n + 1)

return costs[idx][n] + min(choose_red, choose_green)
else:
choose_red = self.helper(costs, idx + 1, n - 2)
choose_blue = self.helper(costs, idx + 1, n - 1)

return costs[idx][n] + min(choose_red, choose_blue)



# MEMOISATION SOLUTION
# Time: O(3n) => which is O(n) because we have 3 colors and n number of houses
# Space: O(3n) => which is O(n) we crate a matrix of n * number of colors

# Just put everything in a memo matrix and use it to optimise on time

class Solution:
def minCost(self, costs: List[List[int]]) -> int:
memo = [[-1 for _ in range(3)] for _ in range(len(costs))]
for m in range(len(costs) -1, -1, -1 ):
if m == len(costs) - 1:
memo[m][0] = costs[m][0]
memo[m][1] = costs[m][1]
memo[m][2] = costs[m][2]
else:
memo[m][0] = costs[m][0] + min(memo[m+1][1], memo[m+1][2])
memo[m][1] = costs[m][1] + min(memo[m+1][0], memo[m+1][2])
memo[m][2] = costs[m][2] + min(memo[m+1][0], memo[m+1][1])

return min(memo[0][0], memo[0][1],memo[0][2])
70 changes: 70 additions & 0 deletions 518. Coin Change II.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Time: O(2^m+n) => m is the amount and n is the no. of elements in coins array
# The time complexity is when we choose until amount is 1 and then we don't choose until the idx is not out of range
# Space: O(m+n) => That's the recursive space that will be used at the end

# Everything is similar to coin change except returning choose + not_choose because we have to count all the possible paths
# Hence we have also changes the base cases accordingly so if amount is 0 it's valid and returns 1 and rest is invalid path which returns 0
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
return self.helper(coins, amount, 0)
def helper(self,coins,amount,idx):
# Base case
if amount == 0:
return 1
if idx > (len(coins) - 1) or amount < 0:
return 0

# choose
choose = self.helper(coins,amount-coins[idx],idx)
# Not choose
not_choose = self.helper(coins,amount,idx+1)

return choose + not_choose

# MEMOIZATION SOLUTION
# Time and Space: O(m * n) where m is the len(coins) and n is the amount

# Just add the values calculate (choose + not_choose) in a memo matrix and use the same amount for repeated sub problems
# Add the result in the memo matrix i.e the additioin of choose and not_choose
# return self.memo[idx][amount] from the function
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
self.memo = [[-1 for _ in range(amount + 1)] for _ in range(len(coins) +1)]

return self.helper(coins, amount, 0)
def helper(self,coins,amount,idx):
# Base case
if amount == 0:
return 1
if idx > (len(coins) - 1) or amount < 0:
return 0
if self.memo[idx][amount] != -1:
return self.memo[idx][amount]

# choose
choose = self.helper(coins,amount-coins[idx],idx)
# Not choose
not_choose = self.helper(coins,amount,idx+1)

self.memo[idx][amount] = choose + not_choose
return self.memo[idx][amount]


# TABULARISATION SOLUTION
# Time and Space: O(m * n) where m is the len(coins) and n is the amount
class Solution:
def change(self, amount: int, coins: List[int]) -> int:
rows = len(coins)
cols = amount
dp_matrix = [[0 for _ in range(cols + 1)] for _ in range(rows + 1)]

for i in range(1,rows + 1):
for j in range(0,cols + 1):
if j == 0:
dp_matrix[i][j] = 1
elif j < coins[i-1]:
dp_matrix[i][j] = dp_matrix[i - 1][j]
else:
dp_matrix[i][j] = dp_matrix[i - 1][j] + dp_matrix[i][j-coins[i - 1]]

return dp_matrix[rows][cols]