粉刷房子 II
难度:
标签:
题目描述
代码结果
运行时间: 32 ms, 内存: 16.8 MB
/*
* Leetcode: Paint House II
* Problem statement: There are a row of n houses, each house can be painted with one of the k colors. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color. The cost of painting each house with a certain color is represented by a n x k cost matrix.
* Find the minimum cost to paint all houses.
*
* Approach: Dynamic Programming with Java Streams
* 1. We will maintain a dp array where dp[i][j] represents the minimum cost to paint house i with color j.
* 2. We will iterate through each house and each color, updating the dp array by adding the cost of painting the current house with the current color to the minimum cost of painting the previous house with a different color.
* 3. The final answer will be the minimum value in the last row of the dp array.
*/
import java.util.Arrays;
import java.util.stream.IntStream;
public class SolutionStream {
public int minCostII(int[][] costs) {
if (costs == null || costs.length == 0) return 0;
int n = costs.length;
int k = costs[0].length;
int[][] dp = new int[n][k];
IntStream.range(0, k).forEach(j -> dp[0][j] = costs[0][j]);
IntStream.range(1, n).forEach(i -> {
IntStream.range(0, k).forEach(j -> {
dp[i][j] = costs[i][j] + IntStream.range(0, k).filter(l -> l != j).map(l -> dp[i - 1][l]).min().orElse(Integer.MAX_VALUE);
});
});
return IntStream.range(0, k).map(j -> dp[n - 1][j]).min().orElse(Integer.MAX_VALUE);
}
}
解释
方法:
这个题解使用了动态规划的思路。定义 dp[j] 表示粉刷第 i 个房子时,第 i-1 个房子使用颜色 j 的最小花费。对于第 i 个房子,遍历每个颜色 j,若第 i-1 个房子使用最小花费的颜色不是 j,则 dp[j] = min_ + costs[i][j],否则 dp[j] = smin_ + costs[i][j],其中 min_ 和 smin_ 分别表示上一轮的最小花费和次小花费。然后更新当前轮的 min_、smin_、mind 和 smind。最后返回最后一轮的最小花费 min_ 即可。
时间复杂度:
O(nk)
空间复杂度:
O(k)
代码细节讲解
🦆
为什么在动态规划中使用两个变量min_和smin_来分别存储最小和次小花费,这样的设计有什么特别的优势?
▷🦆
在更新dp数组时,对于条件`j != mind`使用smin_而不是min_,这种设计的理由是什么?
▷🦆
算法中如何确保每次循环后min_和smin_总是代表当前所有颜色中的最小和次小花费?
▷🦆
在处理边界条件时,如何处理只有一个房子或一个颜色的情况?
▷相关问题
除自身以外数组的乘积
给你一个整数数组 nums
,返回 数组 answer
,其中 answer[i]
等于 nums
中除 nums[i]
之外其余各元素的乘积 。
题目数据 保证 数组 nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请 不要使用除法,且在 O(n)
时间复杂度内完成此题。
示例 1:
输入: nums =[1,2,3,4]
输出:[24,12,8,6]
示例 2:
输入: nums = [-1,1,0,-3,3] 输出: [0,0,9,0,0]
提示:
2 <= nums.length <= 105
-30 <= nums[i] <= 30
- 保证 数组
nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内
进阶:你可以在 O(1)
的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)
滑动窗口最大值
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1 输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length