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.
Note: All costs are positive integers.
Given n
= 3, k
= 3, costs
= [[14,2,11],[11,14,5],[14,3,10]]
return 10
house 0 is color 2, house 1 is color 3, house 2 is color 2, 2 + 5 + 3 = 10
Could you solve it in O(nk)?
Solution 1. Dynamic Programming O(n * k^2) runtime
This solution is based on Paint House. Since we need to check each house with one of the available colors,
so the BCR is O(n * k). The bottleneck of this solution is that it takes O(k) time to find the minimum cost
of the first i - 1 houses with the (i - 1)th house painted with all colors other than the color used to paint
the ith house.
1 public class Solution { 2 public int minCostII(int[][] costs) { 3 if(costs == null || costs.length == 0 || costs[0].length == 0){ 4 return 0; 5 } 6 int n = costs.length; 7 int k = costs[0].length; 8 int[][] T = new int[n + 1][k]; 9 for(int j = 0; j < k; j++){ 10 T[0][j] = 0; 11 } 12 for(int i = 1; i <= n; i++){ 13 for(int j = 0; j < k; j++){ 14 int currMin = Integer.MAX_VALUE; 15 for(int colorIdx = 0; colorIdx < k; colorIdx++){ 16 if(colorIdx != j){ 17 currMin = Math.min(currMin, T[i - 1][colorIdx]); 18 } 19 } 20 T[i][j] = costs[i - 1][j] + currMin; 21 } 22 } 23 int min = Integer.MAX_VALUE; 24 for(int j = 0; j < k; j++){ 25 min = Math.min(min, T[n][j]); 26 } 27 return min; 28 } 29 }
Solution 2. O(n * k) runtime
Important observation:
T[i][j]: the min cost of the ith house painted with color j
preLeast: the min cost of the (i-1)th house
preSecond: the second least min cost of the (i -1)th house
preIndex: the color that was used to paint the (i - 1)th house that gives the min cost of preLeast
T[i][j] = costs[i][j] + preLeast, if j != preIndex
or
T[i][j] = costs[i][j] + preSecond, if j == preIndex
Based on the above observation, we can get preLeast, preSecond and preIndex in the process of
computing all T[i - 1][j], for j = 0..... k - 1. By the time we finish computing all T[i - 1][j], we've
also stored preLeast, preSecond and preIndex for the next house's computation. Having these 3
extra information renders a O(1) time to calculate the min cost of painting the ith house with a fixed color.
The core principle used here is similar with the maximum subarray series problems where if we
don't store and update a minimum prefix sum value as we scan the array, we end up with a O(n^2) runtime.
But if we do store this minimum prefix sum value, we optimize the runtime to O(n).
1 public class Solution { 2 public int minCostII(int[][] costs) { 3 if(costs == null || costs.length == 0 || costs[0].length == 0){ 4 return 0; 5 } 6 int n = costs.length; 7 int k = costs[0].length; 8 int preLeast = 0; 9 int preSecond = 0; 10 int preIndex = -1; 11 int[][] T = new int[n][k]; 12 for(int i = 0; i < n; i++){ 13 int currLeast = Integer.MAX_VALUE; 14 int currSecond = Integer.MAX_VALUE; 15 int currIndex = -1; 16 for(int j = 0; j < k; j++){ 17 if(j == preIndex){ 18 T[i][j] = preSecond + costs[i][j]; 19 }else{ 20 T[i][j] = preLeast + costs[i][j]; 21 } 22 if(T[i][j] < currLeast){ 23 currSecond = currLeast; 24 currLeast = T[i][j]; 25 currIndex = j; 26 }else if(T[i][j] < currSecond){ 27 currSecond = T[i][j]; 28 } 29 } 30 preLeast = currLeast; 31 preSecond = currSecond; 32 preIndex = currIndex; 33 } 34 35 return preLeast; 36 } 37 }
Related Problems