LeetCode 198:打家劫舍(House Robber)------ 题解 ✅
📖 内容概要
你是一个专业的小偷,计划偷窃沿街的房屋。
每间房都有一定数量的现金,但相邻的房屋装有连通的防盗系统 ,
如果两间相邻的房屋在同一晚上被闯入,系统会自动报警。
求在不触动警报的前提下,一夜之内能够偷窃到的最高金额。
✅ 动态规划
✅ 线性 DP
✅ 面试高频题
💡 解题思路(核心)
一、状态定义
java
dp[i] = 到第 i 间房子为止,能偷到的最大金额
二、状态转移方程(最重要)
对于第 i 间房子,有两种选择:
| 选择 | 说明 | 金额 |
|---|---|---|
| 不偷 | 继承前一家的最大金额 | dp[i-1] |
| 偷 | 加上前两家的金额 | dp[i-2] + nums[i] |
java
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
三、边界条件
| 情况 | 说明 |
|---|---|
| 只有一间房 | 只能偷这一间 |
| 有两间房 | 偷金额较大的那一间 |
java
dp[0] = nums[0];
dp[1] = max(nums[0], nums[1]);
✅ AC 代码(Java)
java
class Solution {
public int rob(int[] nums) {
int len = nums.length;
if (len == 1) {
return nums[0];
}
int[] dp = new int[len];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < len; i++) {
dp[i] = Math.max(
dp[i - 1], // 不偷当前房子
dp[i - 2] + nums[i] // 偷当前房子
);
}
return dp[len - 1];
}
}
⏱️ 复杂度分析
| 指标 | 复杂度 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(n)(可优化为 O(1)) |
🚀 空间优化(进阶)
由于 dp[i] 只依赖前两个状态:
java
int prev2 = nums[0];
int prev1 = Math.max(nums[0], nums[1]);
for (int i = 2; i < nums.length; i++) {
int curr = Math.max(prev1, prev2 + nums[i]);
prev2 = prev1;
prev1 = curr;
}
return prev1;
✅ 一句话总结
要么不偷当前房子,要么偷当前房子 + 前两间的最优解,取最大值。
📌 面试加分点(建议记住)
- ✅ 为什么不能偷相邻房间?
- ✅ 为什么是
dp[i-2] + nums[i]而不是dp[i-1] + nums[i]? - ✅ 如何优化空间复杂度?
- ✅ 与「打家劫舍 II(环形房屋)」的关系