{x}
blog image

Paint House II

Solution Explanation for Paint House II

This problem asks for the minimum cost to paint n houses with k colors, ensuring no adjacent houses have the same color. We can solve this efficiently using dynamic programming.

Approach

The dynamic programming approach builds a solution iteratively. We maintain an array f (or a similar data structure) to store the minimum cost to paint the houses up to a certain point.

  1. Initialization: Initialize f with the costs of painting the first house with each color (costs[0]).

  2. Iteration: For each subsequent house (i from 1 to n-1):

    • Create a temporary array g (or modify f in place).
    • For each color j:
      • Find the minimum cost t to paint the previous houses (i-1) with a color different from j. This is the minimum value in f, excluding f[j].
      • Update g[j] as costs[i][j] + t. This represents the minimum cost to paint house i with color j, given the optimal choices for previous houses.
    • Assign g to f for the next iteration.
  3. Result: After iterating through all houses, the minimum value in f represents the overall minimum cost to paint all houses.

Time and Space Complexity

  • Time Complexity: O(nk^2). The nested loops iterate through houses and colors, with an inner loop to find the minimum cost for previous houses. However, this can be optimized to O(nk) as discussed below.
  • Space Complexity: O(k). We primarily use an array f of size k to store the minimum costs.

Optimized Solution (O(n*k))

The crucial optimization is to avoid the inner loop that searches for t (the minimum cost excluding the current color). Instead, we can track the minimum and second minimum costs among the previous houses in constant time.

Here's how the optimized algorithm works:

  1. Initialization: Initialize min1 (minimum cost), min2 (second minimum cost), and min1Idx (index of minimum cost) for the first house.

  2. Iteration: For each subsequent house:

    • Iterate through colors:
      • If the current color is not min1Idx, update the cost using min1.
      • Otherwise, update the cost using min2.
    • Update min1, min2, and min1Idx based on the updated costs.

Code (Optimized - Python)

class Solution:
    def minCostII(self, costs: List[List[int]]) -> int:
        n = len(costs)
        if n == 0:
            return 0
        k = len(costs[0])
        if k == 0:
            return 0
 
        min1, min2, min1Idx = float('inf'), float('inf'), -1
 
        for j in range(k):
            if costs[0][j] < min1:
                min2 = min1
                min1 = costs[0][j]
                min1Idx = j
            elif costs[0][j] < min2:
                min2 = costs[0][j]
 
        for i in range(1, n):
            newMin1, newMin2, newMin1Idx = float('inf'), float('inf'), -1
            for j in range(k):
                cost = costs[i][j]
                if j == min1Idx:
                    cost += min2
                else:
                    cost += min1
 
                if cost < newMin1:
                    newMin2 = newMin1
                    newMin1 = cost
                    newMin1Idx = j
                elif cost < newMin2:
                    newMin2 = cost
 
            min1, min2, min1Idx = newMin1, newMin2, newMin1Idx
 
        return min1
 

The other languages (Java, C++, Go) can be similarly optimized using this approach, reducing the time complexity to O(n*k). The space complexity remains O(1) as we only track a few variables instead of an entire array.