文章目录
1. LeetCode198. House Robber
序列型动态规划问题,仍然按照一般的分析方法进行分析
1.定义状态
最后一步
- 先明确最后的问题是在
前n栋
房子中能够盗取到的最大金额,且相邻的两栋房子不能被同时盗窃 - 无论小偷在前面的房子的决策如何,它一定会在最后一栋房子第
n-1
栋房子决定偷还是不偷,那么就存在两种情况- 选择不偷
第n-1
栋房子,那么在前n
栋房子中盗取金钱的最大值就等于在前n-1
栋房子中盗取金钱的最大值。这个很容易理解嘛,第n-1
栋选择不偷,那最后能盗取到的最大的金额肯定和第n-1
栋房子无关 - 选择偷
第n-1
栋房子- 首先一定会获取偷
第n-1
栋房子带来的金额:nums[n - 1]
- 其次既然偷了
第n-1
栋房子,那么第n-2
栋房子肯定不能被偷了,这个时候在前n
栋房子中盗取金钱的最大值就等于在前n-2
栋房子中盗取金钱的最大值加上nums[n-1]
。(这里的分析要注意前
和第
的区别和对应关系,前n
栋房子的最大值和最后一栋房子,也就是第n-1
栋房子是否被盗有关,这里从第0栋
开始到第n-1栋
结束,一共n
栋房子嘛,也就是对应前n
栋,现在第n-2
栋房子不被盗取,那么前n-1
栋房子的情况就不能被考虑了,因为前n-1
栋房子的最大值是和第n-2
栋房子是否被盗取有关)
- 首先一定会获取偷
- 选择不偷
子问题
- 原问题:
前n栋
房子中能够盗取到的最大金额 - 子问题:
前n-1
栋房子中盗取金钱的最大值;前n-2
栋房子中盗取金钱的最大值
状态
f[i]
:表示盗窃前i
栋房子能获得金钱的最大值
2.转移方程
f[i] = Max{f[i-1], f[i-2] + nums[i-1]}
3.初始值和边界条件
这部分往往根据转移方程来确定,边界条件就是要避免数组越界的位置
f[0] = 0
:前0栋房子能获取的金额的最大值是0
f[1] = nums[0]
f
的计算从i = 2
开始
4.计算顺序
f[0]
f[1]
f[2]
- …
f[n]
- 所以需要开辟一个长度为
n+1
的数组 - 最后返回
f[n]
即可
5.代码
public static int rob_20191111(int[] nums) {
if (nums == null || nums.length == 0){
return 0;
}
int n = nums.length;
//f[0]->f[1]--->f[n-1]--> f[n]
//f[i] : 能在前i户人家中偷盗的最大值
int[] f = new int[n + 1];
//init
f[