Problem Statement (Asked By Facebook)
A builder plans to construct N houses in a row, where each house can be painted in K different colors. The goal is to minimize the total painting cost, ensuring that no two adjacent houses have the same color.
You are given an N × K matrix, where:
- Each row represents a house (
n), and - Each column represents a color (
k). - The value at
matrix[n][k]indicates the cost to paint housenwith colork.
Return the minimum total cost to paint all N houses while satisfying the constraint that no two consecutive houses have the same color.
Problem link: https://leetcode.com/problems/paint-house-iii/description/
Disclaimer: Try solving the problem on your own first! Use this solution only as a reference to learn and improve.
Brute Force Approach: O(K^N) Time Complexity
Step-by-Step Explanation
- Try Every Possible Combination of Colors
- For each house, try every possible color.
- Ensure that no two adjacent houses have the same color.
- Compute the cost for each valid combination.
- Inefficiency
- Exponential Growth: O(K^N) due to recursive branching.
- Overlapping Subproblems: Redundant calculations for different color choices.
Java Code (Brute Force Recursive)
public class PaintHousesBruteForce {
public static int minCostToPaint(int[][] costs) {
if (costs == null || costs.length == 0) return 0;
return helper(costs, 0, -1);
}
private static int helper(int[][] costs, int house, int prevColor) {
if (house == costs.length) return 0; // All houses painted
int minCost = Integer.MAX_VALUE;
for (int color = 0; color < costs[0].length; color++) {
if (color != prevColor) { // Ensure adjacent houses have different colors
int currentCost = costs[house][color] + helper(costs, house + 1, color);
minCost = Math.min(minCost, currentCost);
}
}
return minCost;
}
public static void main(String[] args) {
int[][] costs = {
{1, 3, 5},
{2, 9, 4},
{8, 3, 6},
{4, 7, 2}
};
System.out.println(minCostToPaint(costs)); // Output: 8 (but inefficient)
}
}
Dynamic Programming Approach (O(NK²) Time Complexity)
Step-by-Step Explanation
- Define DP Matrix (
dp[i])- Represents minimum cost to paint house iii with color ccc.
- Transition Formula
- Compute the cost for house iii by taking the minimum cost of painting previous houses, excluding the current color.
- Final Result
- The answer is the minimum value in the last row.
Java Code (O(NK²) DP Solution)
public class PaintHousesDP {
public static int minCostToPaint(int[][] costs) {
if (costs == null || costs.length == 0) return 0;
int N = costs.length, K = costs[0].length;
int[][] dp = new int[N][K];
// Copy first row (base case)
System.arraycopy(costs[0], 0, dp[0], 0, K);
for (int i = 1; i < N; i++) {
for (int c = 0; c < K; c++) {
int minCost = Integer.MAX_VALUE;
for (int prevC = 0; prevC < K; prevC++) {
if (prevC != c) {
minCost = Math.min(minCost, dp[i - 1][prevC]);
}
}
dp[i] = costs[i] + minCost;
}
}
// Return the minimum value from the last row
int minCost = Integer.MAX_VALUE;
for (int cost : dp[N - 1]) {
minCost = Math.min(minCost, cost);
}
return minCost;
}
public static void main(String[] args) {
int[][] costs = {
{1, 3, 5},
{2, 9, 4},
{8, 3, 6},
{4, 7, 2}
};
System.out.println(minCostToPaint(costs)); // Output: 8
}
}
Optimized DP Approach (O(NK) Time Complexity, O(K) Space)
Step-by-Step Explanation
- Track Only the Last Row (
prevRow)- Instead of keeping a full
dp[N][K]table, we store only the last row.
- Instead of keeping a full
- Transition Formula
- Compute minimum values of the previous row.
- Update the current row based on previous minimum cost values.
- Final Result
- Return the minimum value from the last computed row.
Java Code (Optimized O(NK) Space Solution)
public class PaintHousesOptimizedDP {
public static int minCostToPaint(int[][] costs) {
if (costs == null || costs.length == 0) return 0;
int N = costs.length, K = costs[0].length;
int[] prevRow = new int[K];
System.arraycopy(costs[0], 0, prevRow, 0, K); // Copy first row
for (int i = 1; i < N; i++) {
int[] currRow = new int[K];
for (int c = 0; c < K; c++) {
int minCost = Integer.MAX_VALUE;
for (int prevC = 0; prevC < K; prevC++) {
if (prevC != c) {
minCost = Math.min(minCost, prevRow[prevC]);
}
}
currRow = costs[i] + minCost;
}
prevRow = currRow;
}
int minCost = Integer.MAX_VALUE;
for (int cost : prevRow) {
minCost = Math.min(minCost, cost);
}
return minCost;
}
public static void main(String[] args) {
int[][] costs = {
{1, 3, 5},
{2, 9, 4},
{8, 3, 6},
{4, 7, 2}
};
System.out.println(minCostToPaint(costs)); // Output: 8
}
}
Final Optimized Approach (O(NK) Time Complexity, O(1) Space)
Step-by-Step Explanation
- Track Only Three Variables
min1: Smallest cost in the previous row.min1Idx: Index ofmin1.min2: Second smallest cost.
- Use Efficient Update Rule
- If the color is not
min1Idx, usemin1, otherwise usemin2.
- If the color is not
Java Code (Fully Optimized O(NK) Time, O(1) Space)
public class PaintHousesOptimal {
public static int minCostToPaint(int[][] costs) {
if (costs == null || costs.length == 0) return 0;
int N = costs.length, K = costs[0].length;
int min1 = 0, min1Idx = -1, min2 = 0;
for (int i = 0; i < N; i++) {
int newMin1 = Integer.MAX_VALUE, newMin1Idx = -1, newMin2 = Integer.MAX_VALUE;
for (int c = 0; c < K; c++) {
int cost = costs[i] + (c == min1Idx ? min2 : min1);
if (cost < newMin1) {
newMin2 = newMin1;
newMin1 = cost;
newMin1Idx = c;
} else if (cost < newMin2) {
newMin2 = cost;
}
}
min1 = newMin1;
min1Idx = newMin1Idx;
min2 = newMin2;
}
return min1;
}
public static void main(String[] args) {
int[][] costs = {
{1, 3, 5},
{2, 9, 4},
{8, 3, 6},
{4, 7, 2}
};
System.out.println(minCostToPaint(costs)); // Output: 8
}
}
Final Complexity Comparison
| Approach | Time Complexity | Space Complexity |
|---|---|---|
| Brute Force | O(K^N) | O(N) |
| DP Table | O(NK^2) | O(NK) |
| Optimized DP | O(NK) | O(K) |
| Fully Optimized | O(NK) | O(1) |
This final O(NK) time, O(1)space approach is the best possible solution. 🚀
Did this solution help you understand the concept better? Let me know your thoughts in the comments below! Don’t forget to follow us on Instagram @coderz.py for more DSA tips and solutions to ace your coding interviews.
Leave a Comment
You must be logged in to post a comment.