粉刷房子
难度:
标签:
题目描述
代码结果
运行时间: 25 ms, 内存: 16.1 MB
/*
* Leetcode题目: 粉刷房子
* 题目思路: 给定一个n x 3的数组costs,表示粉刷每一栋房子的成本。
* 每一行表示粉刷第i栋房子的成本,costs[i][0]是粉刷成红色的成本,
* costs[i][1]是粉刷成蓝色的成本,costs[i][2]是粉刷成绿色的成本。
* 每一栋房子必须粉刷成一种颜色,并且不能有相邻的两栋房子粉刷成相同的颜色。
* 求粉刷所有房子的最小成本。
*/
import java.util.Arrays;
import java.util.stream.IntStream;
public class PaintHouseStream {
public int minCost(int[][] costs) {
if (costs == null || costs.length == 0) return 0;
int n = costs.length;
int[][] dp = new int[n][3];
dp[0] = Arrays.copyOf(costs[0], 3);
IntStream.range(1, n).forEach(i -> {
dp[i][0] = costs[i][0] + Math.min(dp[i-1][1], dp[i-1][2]);
dp[i][1] = costs[i][1] + Math.min(dp[i-1][0], dp[i-1][2]);
dp[i][2] = costs[i][2] + Math.min(dp[i-1][0], dp[i-1][1]);
});
return IntStream.of(dp[n-1]).min().getAsInt();
}
}
解释
方法:
这个题解使用动态规划的方法来求解最小花费。定义 dp[i][j] 表示粉刷前 i 个房子,且第 i 个房子使用颜色 j 的最小花费。状态转移方程为:dp[i][j] = min(dp[i-1][k]) + costs[i][j],其中 k != j。边界条件为 dp[0][j] = costs[0][j]。最终答案为 min(dp[n-1][0], dp[n-1][1], dp[n-1][2]),即粉刷完所有房子时的最小花费。为了优化空间复杂度,可以只使用一维数组来存储状态,即 dp[j] 表示粉刷当前房子使用颜色 j 的最小花费。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在动态规划中,你是如何考虑初始化`dp`数组的边界情况?请详细解释。
▷🦆
题解中提到的状态转移方程`dp[i][j] = min(dp[i-1][k]) + costs[i][j]`中,k != j的约束是如何在代码中实现的?具体的实现逻辑是什么?
▷🦆
为什么在更新`dp`数组时,选择使用一个新的数组`newDp`来存储更新的值,而不是直接在原有的`dp`数组上进行修改?
▷相关问题
打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1] 输出:4 解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入:[2,7,9,3,1] 输出:12 解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。 偷窃到的最高金额 = 2 + 9 + 1 = 12 。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 400
打家劫舍 II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
示例 1:
输入:nums = [2,3,2] 输出:3 解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
示例 2:
输入:nums = [1,2,3,1] 输出:4 解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。
示例 3:
输入:nums = [1,2,3] 输出:3
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 1000