1. 题目

读题
https://leetcode.cn/problems/house-robber/
考查点
这道题的考查点是动态规划的基本思想和应用,
- 即如何将一个复杂的问题分解成更小的子问题,
- 如何找到问题的状态和状态转移方程,
- 如何确定问题的边界条件和初始值,
- 以及如何用代码来实现动态规划的算法。
2. 解法
思路
一个可能的解决方案是使用一个一维数组dp来存储每个房屋的最大收益,
dp[i]表示从第0个房屋到第i个房屋能够偷窃的最大金额。
那么对于每个房屋,
我们有两种选择:偷或者不偷。
如果我们偷第i个房屋,那么我们不能偷第i-1个房屋,所以dp[i] = dp[i-2] + nums[i]。
如果我们不偷第i个房屋,那么我们可以偷第i-1个房屋,所以dp[i] = dp[i-1]。
我们要取这两种情况的较大值,所以dp[i] = max(dp[i-1], dp[i-2] + nums[i])。
代码逻辑
我可以用以下的步骤来描述代码的逻辑:
- 首先,我检查输入的数组是否为空或者长度为0,如果是,就直接返回0,因为没有房屋可以偷窃。
- 其次,我检查输入的数组的长度是否为1,如果是,就直接返回数组的第一个元素,因为只有一间房屋可以偷窃。
- 然后,我创建一个一维数组dp来存储每个房屋的最大收益,数组的长度和输入的数组相同。我初始化dp[0]为nums[0],dp[1]为nums[0]和nums[1]中的较大值。
- 接着,我从第2个房屋开始遍历输入的数组,对于每个房屋,我用状态转移方程来更新dp[i],即dp[i] = max(dp[i-1], dp[i-2] + nums[i])。
- 最后,我返回dp[n-1]作为最终结果,其中n是输入数组的长度。
具体实现
class Solution {
public int rob(int[] nums) {
// 边界条件
if (nums == null || nums.length == 0) {
return 0;
}
if (nums.length == 1) {
return nums[0];
}
// 创建dp数组
int n = nums.length;
int[] dp = new int[n];
// 初始化
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
// 遍历
for (int i = 2; i < n; i++) {
// 状态转移方程
dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]);
}
// 返回结果
return dp[n-1];
}
}
3. 总结
浙公网安备 33010602011771号