力扣 LCR 091. 粉刷房子 —— 动态规划入门详解
引言动态规划是算法面试中的拦路虎许多初学者不知从何下手。今天讲解的「力扣 91. 粉刷房子」正是 DP 入门的绝佳练习题。它不像背包问题需要纠结容量维度而是用最朴素的二维 DP 表格清晰展示了状态定义、初始化、转移和返回的完整流程。无论你是算法新手还是面试备战者这篇文章都会带你一步步拆解题目让你真正理解 DP 的核心思想。让我们从一道题开始打通动态规划的任督二脉摘要本文详细解析力扣 91「粉刷房子」的 DP 解法。给定n×3成本矩阵求相邻颜色不同时的最小总花费。定义dp[i][j]为第i个房子刷颜色j的最小花费转移方程dp[i][j]costs[i][j]min(dp[i-1][k]) (k≠j)。通过示例手动推导 DP 表格并提供二维数组和 O(1) 滚动数组两种代码实现。重点总结三个易错点维度理解、返回值、三数取最小值。时间 O(n)空间可优化至 O(1)目录一、题目描述二、动态规划思路1. 为什么用 DP2. DP 数组的定义3. DP 数组的构造以示例为例4. 状态转移方程三、Java 代码实现四、代码优化空间压缩五、易错点总结特别重要⚠️ 注意点 1DP 数组的构造维度⚠️ 注意点 2返回值不是 dp[n-1][2]⚠️ 注意点 3三个数取最小值的写法六、复杂度分析总结一、题目描述假如有一排房子共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二、动态规划思路1. 为什么用 DP这道题满足最优子结构第i个房子刷某种颜色的最小花费只依赖于第i-1个房子刷其他两种颜色的最小花费。因此我们可以用动态规划从前往后依次推导。2. DP 数组的定义我们定义一个二维数组dpdp[i][j]表示粉刷完前 i 个房子0 ~ i且第 i 个房子刷成颜色 j 时的最小总花费。其中i表示房子编号范围0 ~ n-1j表示颜色0红色1蓝色2绿色3. DP 数组的构造以示例为例输入costs [[17,2,17], [16,16,5], [14,3,19]]我们手动构造出dp数组房子 \ 颜色红色蓝色绿色0号房子172171号房子183372号房子211037推导过程初始化第一行第 0 号房子刷任意颜色花费就是它本身的成本。→dp[0] [17, 2, 17]第二行1号房子刷红色16 min(dp[0][1], dp[0][2]) 16 min(2,17) 18刷蓝色16 min(dp[0][0], dp[0][2]) 16 min(17,17) 33刷绿色5 min(dp[0][0], dp[0][1]) 5 min(17,2) 7第三行2号房子刷红色14 min(dp[1][1], dp[1][2]) 14 min(33,7) 21刷蓝色3 min(dp[1][0], dp[1][2]) 3 min(18,7) 10刷绿色19 min(dp[1][0], dp[1][1]) 19 min(18,33) 37最终最后一个房子2号房子的最小花费是min(21, 10, 37) 104. 状态转移方程dp[i][j] costs[i][j] min(dp[i-1][k]) 其中 k ≠ j也就是说当前房子刷颜色j的总花费 当前房子刷颜色j的成本 上一个房子刷另外两种颜色的较小值。三、Java 代码实现public class Main { public static void main(String[] args) { int[][] costs {{17, 2, 17}, {16, 16, 5}, {14, 3, 19}}; System.out.println(minCost(costs)); // 输出 10 } public static int minCost(int[][] costs) { int M costs.length; // 房子数量 int N 3; // 颜色数量红、蓝、绿 // dp[i][j]前 i 个房子第 i 个房子刷颜色 j 的最小总花费 int[][] dp new int[M][N]; // 1. 初始化第一行 for (int j 0; j N; j) { dp[0][j] costs[0][j]; } // 2. 从第二个房子开始递推 for (int i 1; i M; i) { for (int j 0; j N; j) { int prevMin; if (j 0) { // 当前刷红色上一个只能是蓝色或绿色 prevMin Math.min(dp[i-1][1], dp[i-1][2]); } else if (j 1) { // 当前刷蓝色上一个只能是红色或绿色 prevMin Math.min(dp[i-1][0], dp[i-1][2]); } else { // 当前刷绿色上一个只能是红色或蓝色 prevMin Math.min(dp[i-1][0], dp[i-1][1]); } dp[i][j] costs[i][j] prevMin; } } // 3. 返回最后一个房子的最小花费 return Math.min(dp[M-1][0], Math.min(dp[M-1][1], dp[M-1][2])); } }运行结果四、代码优化空间压缩因为dp[i]只依赖于dp[i-1]我们可以用一维数组滚动更新降低空间复杂度到O(1)public static int minCost(int[][] costs) { int n costs.length; int[] dp new int[3]; // 初始化第一行 dp[0] costs[0][0]; dp[1] costs[0][1]; dp[2] costs[0][2]; for (int i 1; i n; i) { int prev0 dp[0], prev1 dp[1], prev2 dp[2]; dp[0] costs[i][0] Math.min(prev1, prev2); dp[1] costs[i][1] Math.min(prev0, prev2); dp[2] costs[i][2] Math.min(prev0, prev1); } return Math.min(dp[0], Math.min(dp[1], dp[2])); }五、易错点总结特别重要⚠️ 注意点 1DP 数组的构造维度本题虽然只有一个“房子数量”维度但因为每个状态有 3 种颜色选择所以用二维数组dp[n][3]来记录。不要误以为需要“物品 容量”两个维度那是 01 背包的思路这里没有容量限制。⚠️ 注意点 2返回值不是dp[n-1][2]很多同学想当然地认为最后一个元素就是答案但这是错误的最后一个房子有三种可能颜色应该取三种颜色中的最小值return Math.min(dp[M-1][0], Math.min(dp[M-1][1], dp[M-1][2]));⚠️ 注意点 3三个数取最小值的写法Java 中Math.min()只支持两个参数取三个数最小值要嵌套Math.min(a, Math.min(b, c))六、复杂度分析时间复杂度O(n * 3) O(n)只需要遍历每个房子一次空间复杂度二维数组版O(n * 3) O(n)一维滚动数组版O(1)总结这道题是动态规划入门的经典题目核心思想是定义dp[i][j]表示第i个房子刷颜色j时的最小花费状态转移只依赖于前一个房子的两种颜色最后取最后一个房子的三种颜色中的最小值掌握了这道题后续遇到“打家劫舍”、“股票买卖”等经典 DP 问题思路也会更加清晰。希望这篇文章能帮助你更好地理解动态规划如果有问题欢迎留言讨论

相关新闻

基于simulink的双向DC/AC接口变换器的系统效率

基于simulink的双向DC/AC接口变换器的系统效率

### 手把手教你学Simulink--直流微电网中双向DC/AC接口变换器的电压稳定控制 #### 摘要 随着能源转型的推进,直流微电网在分布式能源接入与供电可靠性提升方面发挥着日益重要的作用。双向DC/AC接口变换器作为直流微电网与交流电网能量交互的关键设备,其电压稳定控制对于保障…

2026/7/21 23:57:15阅读更多 →
KVM主题:大页内存HugePages配置实践

KVM主题:大页内存HugePages配置实践

KVM主题:大页内存HugePages配置实践 在虚拟化环境中,内存管理是影响性能的关键因素之一。KVM(Kernel-based Virtual Machine)作为Linux内核中的一个虚拟化模块,为虚拟机提供了高效的硬件虚拟化支持。为了进一步提升KVM…

2026/7/21 23:57:15阅读更多 →
【Python自动化】安全库存阈值不同?库管/小白1个脚本预警

【Python自动化】安全库存阈值不同?库管/小白1个脚本预警

为什么你需要这个脚本 管多品类库存有多痛苦? 在仓库、仓库管理系统中管理货品时,出现令库管烦恼的问题是:把所有货品的安全库存阈值(即剩下多少件就预警且提示该补货/进货)设为统一标准,导致销量快的货总…

2026/7/21 23:57:15阅读更多 →
开源vs闭源AI语音引擎对比报告(Whisper/VoiceCraft/Paraformer/SenseVoice全解析)

开源vs闭源AI语音引擎对比报告(Whisper/VoiceCraft/Paraformer/SenseVoice全解析)

更多请点击: https://kaifayun.com 第一章:开源vs闭源AI语音引擎对比报告(Whisper/VoiceCraft/Paraformer/SenseVoice全解析) 近年来,语音识别与合成技术加速演进,开源引擎凭借透明性、可定制性与社区活力…

2026/7/22 2:06:08阅读更多 →
大模型微调实战:从LoRA到部署全流程解析

大模型微调实战:从LoRA到部署全流程解析

1. 大模型微调入门指南大模型微调(Fine-tuning)是当前AI领域最热门的技术方向之一。简单来说,它就像给一个已经受过高等教育的"学霸"进行专业领域的特训。这个"学霸"已经掌握了丰富的通用知识(预训练模型),而我们只需要用特定领域的…

2026/7/22 2:06:08阅读更多 →
TI PSC电源管理:嵌入式低功耗设计核心机制与实战避坑指南

TI PSC电源管理:嵌入式低功耗设计核心机制与实战避坑指南

1. 项目概述与核心价值在嵌入式系统,尤其是电池供电的物联网设备、便携式医疗仪器或工业传感器节点中,功耗管理从来都不是一个“锦上添花”的功能,而是决定产品成败的关键。我经历过不止一个项目,因为早期对功耗管理重视不足&…

2026/7/22 2:06:08阅读更多 →
Linux下的grep

Linux下的grep

可以通过grep命令,从文件中通过关键字过滤文件行。 语法:grep [-n] 关键字 文件路径 选项-n,可选,表示在结果中显示匹配的行的行号。 参数,关键字,必填,表示过滤的关键字,带有空格或其它特殊符号…

2026/7/22 2:06:08阅读更多 →
Hermes Agent 桌面端:把终端智能体变成可视化工作台,文件与会话一屏管好

Hermes Agent 桌面端:把终端智能体变成可视化工作台,文件与会话一屏管好

Hermes Agent 桌面端:把终端智能体变成可视化工作台,文件与会话一屏管好 [!NOTE] 很多初学者把智能体当成“更会聊天的模型”,结果一上手就把文件、网络和高权限命令交出去。本篇围绕 桌面端 建立一套可复现的实践路径:先明确任务边界,再确认工具与权限,最后用日志和结果…

2026/7/22 2:06:08阅读更多 →
解决Docker与SELinux兼容性问题指南

解决Docker与SELinux兼容性问题指南

1. SELinux与Docker的兼容性问题解析当你在Linux系统上启动Docker容器时遇到"Job for docker.service failed"错误,十有八九是SELinux在作祟。作为Linux内核的安全模块,SELinux通过强制访问控制(MAC)机制为系统提供额外的安全层,但…

2026/7/22 2:04:08阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →