持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第32天,点击查看活动详情
题目描述
假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。
例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。
请计算出粉刷完所有房子最少的花费成本。
示例 1:
输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色。
最少花费: 2 + 5 + 3 = 10。
示例 2:
输入: costs = [[7,6,2]]
输出: 2
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/JEj789
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路分析
- 今天的算法题目是粉刷房子题目,题目比较长。重点如下。
-
- 题目给出的是 costs 数组,代表刷一个房子,使用不同颜色,需要不同的花费。
-
- 粉刷房子的时候,需要使其相邻的两个房子颜色不相同。
-
- 我们需要求解的是粉刷房子的最小花费。
- 根据上述关键点的分析,我们可以采用动态规划思想来做这个题目。动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
- 具体到这个题目子问题就是求解每一层的粉刷花费。就是关键点2。我们初始化二维DP数组,这个题目只有3种颜色。直接使用 cost[0][0],cost[0][1],cost[0][2] 初始化。由于相邻房子颜色不能相同。动态转移方程为
//第i个房子刷第一个颜色
dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0];
//第i个房子刷第二个颜色
dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1];
//第i个房子刷第三个颜色
dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2];
- dp方程计算完成之后,找出最小值就是答案。具体实现代码如下,供参考。
通过代码
class Solution {
public int minCost(int[][] costs) {
int n = costs.length;
int[][] dp = new int[n][3];
//刷第一个颜色
dp[0][0] = costs[0][0];
//刷第二个颜色
dp[0][1] = costs[0][1];
//刷第三个颜色
dp[0][2] = costs[0][2];
for (int i = 1; i < n; i++) {
//第i个房子刷第一个颜色
dp[i][0] = Math.min(dp[i - 1][1], dp[i - 1][2]) + costs[i][0];
//第i个房子刷第二个颜色
dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]) + costs[i][1];
//第i个房子刷第三个颜色
dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]) + costs[i][2];
}
return Math.min(Math.min(dp[n - 1][0], dp[n - 1][1]), dp[n - 1][2]);
}
}
总结
- 上述算法的时间复杂度是O(n), 空间复杂度是O(n)
- 坚持算法每日一题,加油!