[LeetCode 265] Paint House II

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 0costs[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.
Example

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

Challenge 

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 

Paint House

posted @ 2020-09-23 13:03  Review->Improve  阅读(158)  评论(0编辑  收藏  举报