零 標題:演算法(leetcode,附思維導圖 + 全部解法)300題之(劍指 Offer II 091)粉刷房子
一 題目描述
二 解法總覽(思維導圖)
三 全部解法
1 方案1
1)程式碼:
// 方案1 “自己。動態規劃法”。
// 用時:10:47 - 10:57。
// 想法:
// 1)“題幹有最字眼,優先考慮動態規劃”。
// 2)狀態定義:dp[i][j] —— 以房子i結尾 且 其刷成顏色j 的最低價格。
// 3)狀態轉移:dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + costs[i][j]);
// i的範圍:[1, l - 1],j的範圍:[0, 2],j與k的關係 j !== k 。
// 思路:
// 1)狀態初始化:l = costs.length;
// dp = new Array(l).fill(0).map(v => new Array(3).fill(Number.POSITIVE_INFINITY));
// dp[0] = costs[0]; 。
// 2)核心:狀態轉移:dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + costs[i][j]);
// i的範圍:[1, l - 1],j的範圍:[0, 2],j與k的關係 j !== k 。
// 3)返回結果:Math.min(...dp[l - 1]); 。
var minCost = function(costs) {
// 1)狀態初始化:l = costs.length;
// dp = new Array(l).fill(0).map(v => new Array(3).fill(Number.POSITIVE_INFINITY));
// dp[0] = costs[0]; 。
const l = costs.length;
let dp = new Array(l).fill(0).map(v => new Array(3).fill(Number.POSITIVE_INFINITY));
dp[0] = costs[0];
// 2)核心:狀態轉移:dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + costs[i][j]);
// i的範圍:[1, l - 1],j的範圍:[0, 2],j與k的關係 j !== k 。
for (let i = 1; i < l; i++) {
// 注:如下6行程式碼等價於如下
// for (let j = 0; j <= 2; j++) {
// for (let k = 0; k <= 2; k++) {
// if (j !== k) {
// dp[i][j] = Math.min(dp[i][j], dp[i - 1][k] + costs[i][j]);
// }
// }
// }
dp[i][0] = Math.min(dp[i][0], dp[i - 1][1] + costs[i][0]);
dp[i][0] = Math.min(dp[i][0], dp[i - 1][2] + costs[i][0]);
dp[i][1] = Math.min(dp[i][1], dp[i - 1][0] + costs[i][1]);
dp[i][1] = Math.min(dp[i][1], dp[i - 1][2] + costs[i][1]);
dp[i][2] = Math.min(dp[i][2], dp[i - 1][0] + costs[i][2]);
dp[i][2] = Math.min(dp[i][2], dp[i - 1][1] + costs[i][2]);
}
// 3)返回結果:Math.min(...dp[l - 1]); 。
return Math.min(...dp[l - 1]);
};
2 方案2
1)程式碼:
// 方案2 “官方。動態規劃 - 滾動陣列法”。
// 參考:
// 1)https://leetcode.cn/problems/JEj789/solution/fen-shua-fang-zi-by-leetcode-solution-q0kh/
// 想法:
// 0)“題幹有最字眼,優先考慮動態規劃”。
// 1)狀態定義:dp[i][j] —— 以房子i結尾 且 其刷成顏色j 的最低價格。
// 2)狀態轉移方程:dp[i][j] = min(dp[i − 1][(j + 1) % 3],dp[i − 1][(j + 2) % 3]) + costs[i][j],
// 1 ≤ i < n 和 0 ≤ j < 3。
// 思路:
// 1)狀態初始化:l =costs.length; dp = costs[0]; 。
// 2)核心:狀態轉移 —— dp[i][j] = min(dp[i − 1][(j + 1) % 3],dp[i − 1][(j + 2) % 3]) + costs[i][j],
// 1 ≤ i < n 和 0 ≤ j < 3。
// 3)返回結果:Math.min(...dp); 。
var minCost = function(costs) {
// 1)狀態初始化:l =costs.length; dp = costs[0]; 。
const l =costs.length;
let dp = costs[0];
// 2)核心:狀態轉移 —— dp[i][j] = min(dp[i − 1][(j + 1) % 3],dp[i − 1][(j + 2) % 3]) + costs[i][j],
// 1 ≤ i < n 和 0 ≤ j < 3。
for (let i = 1; i < l; i++) {
dpNew = new Array(3).fill(0);
for (let j = 0; j < 3; j++) {
dpNew[j] = Math.min(dp[(j + 1) % 3], dp[(j + 2) % 3]) + costs[i][j];
}
dp = dpNew;
}
// 3)返回結果:Math.min(...dp); 。
return Math.min(...dp);
};
四 資源分享 & 更多
1 歷史文章 - 總覽
2 博主簡介
碼農三少 ,一個致力於編寫 極簡、但齊全題解(演算法) 的博主。
專注於 一題多解、結構化思維 ,歡迎一起刷穿 LeetCode ~