跳转至

265. 粉刷房子 II 🔒

题目描述

假如有一排房子共有 n 幢,每个房子可以被粉刷成 k 种颜色中的一种。房子粉刷成不同颜色的花费成本也是不同的。你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。

每个房子粉刷成不同颜色的花费以一个 n x k 的矩阵表示。

  • 例如,costs[0][0] 表示第 0 幢房子粉刷成 0 号颜色的成本;costs[1][2] 表示第 1 幢房子粉刷成 2 号颜色的成本,以此类推。

返回 粉刷完所有房子的最低成本 。

 

示例 1:

输入: costs = [[1,5,3],[2,9,4]]
输出: 5
解释: 
将房子 0 刷成 0 号颜色,房子 1 刷成 2 号颜色。花费: 1 + 4 = 5; 
或者将 房子 0 刷成 2 号颜色,房子 1 刷成 0 号颜色。花费: 3 + 2 = 5. 

示例 2:

输入: costs = [[1,3],[2,4]]
输出: 5

 

提示:

  • costs.length == n
  • costs[i].length == k
  • 1 <= n <= 100
  • 2 <= k <= 20
  • 1 <= costs[i][j] <= 20

 

进阶:您能否在 O(nk) 的时间复杂度下解决此问题?

解法

方法一:动态规划

定义 \(f[i][j]\) 表示粉刷前 \(i\) 个房子,且最后一个房子被粉刷成第 \(j\) 种颜色的最小花费。答案为 \(\min_{0 \leq j < k} f[n][j]\)

对于 \(f[i][j]\),可以从 \(f[i - 1][j']\) 转移而来,其中 \(j' \neq j\)。因此,可以得到状态转移方程:

\[ f[i][j] = \min_{0 \leq j' < k, j' \neq j} f[i - 1][j'] + costs[i - 1][j] \]

由于 \(f[i][j]\) 只与 \(f[i - 1][j']\) 有关,因此可以使用滚动数组优化空间复杂度。

时间复杂度 \(O(n \times k^2)\),空间复杂度 \(O(k)\)。其中 \(n\)\(k\) 分别为房子数量和颜色数量。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Solution:
    def minCostII(self, costs: List[List[int]]) -> int:
        n, k = len(costs), len(costs[0])
        f = costs[0][:]
        for i in range(1, n):
            g = costs[i][:]
            for j in range(k):
                t = min(f[h] for h in range(k) if h != j)
                g[j] += t
            f = g
        return min(f)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public int minCostII(int[][] costs) {
        int n = costs.length, k = costs[0].length;
        int[] f = costs[0].clone();
        for (int i = 1; i < n; ++i) {
            int[] g = costs[i].clone();
            for (int j = 0; j < k; ++j) {
                int t = Integer.MAX_VALUE;
                for (int h = 0; h < k; ++h) {
                    if (h != j) {
                        t = Math.min(t, f[h]);
                    }
                }
                g[j] += t;
            }
            f = g;
        }
        return Arrays.stream(f).min().getAsInt();
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
    int minCostII(vector<vector<int>>& costs) {
        int n = costs.size(), k = costs[0].size();
        vector<int> f = costs[0];
        for (int i = 1; i < n; ++i) {
            vector<int> g = costs[i];
            for (int j = 0; j < k; ++j) {
                int t = INT_MAX;
                for (int h = 0; h < k; ++h) {
                    if (h != j) {
                        t = min(t, f[h]);
                    }
                }
                g[j] += t;
            }
            f = move(g);
        }
        return *min_element(f.begin(), f.end());
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func minCostII(costs [][]int) int {
    n, k := len(costs), len(costs[0])
    f := cp(costs[0])
    for i := 1; i < n; i++ {
        g := cp(costs[i])
        for j := 0; j < k; j++ {
            t := math.MaxInt32
            for h := 0; h < k; h++ {
                if h != j && t > f[h] {
                    t = f[h]
                }
            }
            g[j] += t
        }
        f = g
    }
    return slices.Min(f)
}

func cp(arr []int) []int {
    t := make([]int, len(arr))
    copy(t, arr)
    return t
}

评论

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy