Paint House 2 - N houses with k colors with no two adjacent houses with same color color
Problem
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 a n x k cost matrix. For example, 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... Find the minimum cost to paint all houses.
Examples
Example 1
Input:
costs =[[14,2,11],[11,14,5],[14,3,10]]
Output: 10
Explanation:
The three house use color [1,2,1] for each house. The total cost is 10.
Example 2
Input:
costs =[[5]]
Output: 5
Explanation:
There is only one color and one house.
Challenge
Could you solve it in O(n*k).
Constraints
All costs are positive integers.
Solution
This problem is similar to [Paint House 1 - N houses with 3 colors with no two adjacent houses with same color](paint-house-1-n-houses-with-3-colors-with-no-two-adjacent-houses-with-same-color), but with k colors instead of 3.
Method 1 - Recursion
Code
Java
class Solution {
public int minCostII(int[][] costs) {
return minCostRecursive(costs, 0, -1);
}
private int helper(int[][] costs, int house, int lastColor) {
if (house == costs.length) {
return 0;
}
int min = Integer.MAX_VALUE;
for (int color = 0; color < costs[0].length; color++) {
if (color != lastColor) {
int cost = costs[house][color] + helper(costs, house + 1, color);
min = Math.min(min, cost);
}
}
return min;
}
}
Method 2 - Top Down DP
Code
Java
public class Solution {
private Integer[][] memo;
public int minCostII(int[][] costs) {
memo = new Integer[costs.length][costs[0].length];
return minCostRecursive(costs, 0, -1);
}
private int helper(int[][] costs, int house, int lastColor) {
if (house == costs.length) {
return 0;
}
if (lastColor != -1 && memo[house][lastColor] != null) {
return memo[house][lastColor];
}
int min = Integer.MAX_VALUE;
for (int color = 0; color < costs[0].length; color++) {
if (color != lastColor) {
int cost = costs[house][color] + helper(costs, house + 1, color);
min = Math.min(min, cost);
}
}
if (lastColor != -1) {
memo[house][lastColor] = min;
}
return min;
}
}
Method 3 - DP
This is a classic back pack problem.
- Define dp[n][k], where dp[i][j] means for house i with color j the minimum cost.
- Initial value: dp[0][j] = costs[0][j]. For others, dp[i][j] = Integer.MAX_VALUE;, i >= 1
- Transit function: dp[i][j] = Math.min(dp[i][j], dp[i-1][k] + cost[i][j]), where k != j.
- Final state: Min(dp[n-1][k]).
Code
Java
public int minCostII(int[][] costs) {
if (costs == null || costs.length == 0) {
return 0;
}
int n = costs.length;
int k = costs[0].length;
// dp[i][j] means the min cost painting for house i, with color j
int[][] dp = new int[n][k];
// Initialize the first row of the DP table with the costs of painting the first house with each color
for (int color = 0; color < k; color++) {
dp[0][color] = costs[0][color];
}
for (int house = 1; house < n; house++) {
for (int color = 0; color < k; color++) {
dp[house][color] = costs[house][color] + findMin(dp[house - 1], color);
}
}
// Final state
int minCost = Integer.MAX_VALUE;
for (int i = 0; i < k; i++) {
minCost = Math.min(minCost, dp[n - 1][i]);
}
return minCost;
}
Complexity
- ⏰ Time complexity:
O(n*k*k) - 🧺 Space complexity:
O(n*k)
Method 4 - Space Optimized DP
Since dp[i][k] only depends on dp[i-1][j], we can use a 1-D DP solution.
Code
Java
public int minCostII(int[][] costs) {
if (costs == null || costs.length == 0) {
return 0;
}
int n = costs.length;
int k = costs[0].length;
// dp[j] means the min cost for color j
int[] dp1 = new int[k];
int[] dp2 = new int[k];
// Initialization
for (int i = 0; i < k; i++) {
dp1[i] = costs[0][i];
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < k; j++) {
dp2[j] = Integer.MAX_VALUE;
for (int m = 0; m < k; m++) {
if (m != j) {
dp2[j] = Math.min(dp1[m] + costs[i][j], dp2[j]);
}
}
}
for (int j = 0; j < k; j++) {
dp1[j] = dp2[j];
}
}
// Final state
int minCost = Integer.MAX_VALUE;
for (int i = 0; i < k; i++) {
minCost = Math.min(minCost, dp1[i]);
}
return minCost;
}
Complexity
- ⏰ Time complexity:
O(n*k*k) - 🧺 Space complexity:
O(k)