There are a row of n
houses, each house can be painted with one of the k
colors. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color.
The cost of painting each house with a certain color is represented by an n x k
cost matrix costs
.
costs[0][0]
is the cost of painting house 0
with color 0
; costs[1][2]
is the cost of painting house 1
with color 2
, and so on...Return the minimum cost to paint all houses.
Example 1:
Input: costs = [[1,5,3],[2,9,4]]
Output: 5
Explanation:
You have to paint house 0. Firstly, paint it with color 0, cost 1. Then paint house 1 with color 2, cost 4.
Total cost: 1 + 4 = 5;
Or you can paint house 0 with color 2, cost 3. Then paint house 1 with color 0, cost 2.
Total cost: 3 + 2 = 5.
Example 2:
Input: costs = [[1,3],[2,4]]
Output: 5
Constraints:
costs.length == n
costs[i].length == k
1 <= n <= 100
1 <= k <= 20
0 <= costs[i][j] <= 1000
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine painting a row of houses with different colored paints, where each house has a cost for each color. The brute force way is to try every possible color combination for the houses. We want to find the cheapest combination.
Here's how the algorithm would work step-by-step:
def paint_house_two_brute_force(costs):
number_of_houses = len(costs)
if number_of_houses == 0:
return 0
number_of_colors = len(costs[0])
minimum_cost = float('inf')
def calculate_cost(house_index, current_painting_scheme, total_cost):
nonlocal minimum_cost
# Base case: all houses are painted
if house_index == number_of_houses:
minimum_cost = min(minimum_cost, total_cost)
return
# Try each color for the current house
for color_index in range(number_of_colors):
# Ensure different colors for adjacent houses
if house_index > 0 and current_painting_scheme[house_index - 1] == color_index:
continue
# Recursively calculate cost with the current color
current_painting_scheme[house_index] = color_index
calculate_cost(house_index + 1, current_painting_scheme, total_cost + costs[house_index][color_index])
# Initialize the painting scheme
painting_scheme = [0] * number_of_houses
# Start the recursive process
calculate_cost(0, painting_scheme, 0)
return minimum_cost
This problem is about finding the cheapest way to paint houses with different colors, making sure no two adjacent houses have the same color. The key idea is to build up the solution step-by-step, only remembering the best and second-best costs from the previous step, allowing us to make efficient decisions for each house.
Here's how the algorithm would work step-by-step:
def paint_house_ii(costs):
number_of_houses = len(costs)
if number_of_houses == 0:
return 0
number_of_colors = len(costs[0])
# Initialize best and second best costs
minimum_cost = 0
second_minimum_cost = 0
minimum_cost_index = -1
# Iterate through each house
for house_index in range(number_of_houses):
previous_minimum_cost = minimum_cost
previous_second_minimum_cost = second_minimum_cost
previous_minimum_cost_index = minimum_cost_index
minimum_cost = float('inf')
second_minimum_cost = float('inf')
minimum_cost_index = -1
# Iterate through each color
for color_index in range(number_of_colors):
# If current color is same as prev min,
# use prev second min.
if color_index == previous_minimum_cost_index:
current_cost = costs[house_index][color_index] + previous_second_minimum_cost
# Otherwise, use previous min.
else:
current_cost = costs[house_index][color_index] + previous_minimum_cost
# Update min costs for the current house
if current_cost < minimum_cost:
second_minimum_cost = minimum_cost
minimum_cost = current_cost
minimum_cost_index = color_index
elif current_cost < second_minimum_cost:
second_minimum_cost = current_cost
# The min cost after painting all houses.
return minimum_cost
Case | How to Handle |
---|---|
Null or empty costs array | Return 0 immediately as there are no houses to paint. |
Zero houses (n=0) | Return 0 as there are no costs. |
One house (n=1) and one color (k=1) | Return the cost of that single color for that single house. |
One house (n=1) and multiple colors (k>1) | Return the minimum cost among all colors for the single house. |
Multiple houses (n>1) and one color (k=1) | Return -1, because adjacent houses can't be the same color; an alternative is to throw an IllegalArgumentException. |
Large input sizes (n and k very large) exceeding memory or time limits | Ensure the algorithm has optimal time complexity (O(n*k)) to prevent timeouts and uses memory efficiently to avoid exceeding available memory. |
All costs are zero for some house | The algorithm should still correctly propagate the minimum cost, treating zero as the minimum. |
Integer overflow when summing costs with large values | Use a larger data type (e.g., long) to store the intermediate and final cost values. |