1
- class Solution (object ):
2
- def rob (self , nums ):
3
- """
4
- :type nums: List[int]
5
- :rtype: int
6
- """
7
- if len (nums ) == 0 :
8
- return 0
9
- if len (nums ) <= 2 :
10
- return max (nums )
11
- nums [1 ] = max (nums [0 ], nums [1 ])
12
- for i in range (2 , len (nums )):
13
- nums [i ] = max (nums [i - 2 ] + nums [i ], nums [i - 1 ])
14
- return max (nums ) if nums else 0
1
+ 状态定义 :
2
+ 设动态规划列表 dpdpdp ,dp [i ]dp [i ]dp [i ] 代表前 iii 个房子在满足条件下的能偷窃到的最高金额 。
3
+
4
+ 转移方程 :
5
+ 设 : 有 nnn 个房子 ,前 nnn 间能偷窃到的最高金额是 dp [n ]dp [n ]dp [n ] ,前 n −1 n - 1 n −1 间能偷窃到的最高金额是 dp [n −1 ]dp [n - 1 ]dp [n −1 ] ,此时向这些房子后加一间房 ,此房间价值为 numnumnum ;
6
+ 加一间房间后 : 由于不能抢相邻的房子 ,意味着抢第 n + 1 n + 1 n + 1 间就不能抢第 nnn 间 ;那么前 n + 1 n + 1 n + 1 间房能偷取到的最高金额 dp [n + 1 ]dp [n + 1 ]dp [n + 1 ] 一定是以下两种情况的 较大值 :
7
+
8
+ 不抢第 n + 1 n + 1 n + 1 个房间 ,因此等于前 nnn 个房子的最高金额 ,即 dp [n + 1 ]= dp [n ]dp [n + 1 ] = dp [n ]dp [n + 1 ]= dp [n ] ;
9
+ 抢第 n + 1 n + 1 n + 1 个房间 ,此时不能抢第 nnn 个房间 ;因此等于前 n −1 n - 1 n −1 个房子的最高金额加上当前房间价值 ,即 dp [n + 1 ]= dp [n −1 ]+ numdp [n + 1 ] = dp [n - 1 ] + numdp [n + 1 ]= dp [n −1 ]+ num ;
10
+ 细心的我们发现 : 难道在前 nnn 间的最高金额 dp [n ]dp [n ]dp [n ] 情况下 ,第 nnn 间一定被偷了吗 ?假设没有被偷 ,那 n + 1 n + 1 n + 1 间的最大值应该也可能是 dp [n + 1 ]= dp [n ]+ numdp [n + 1 ] = dp [n ] + numdp [n + 1 ]= dp [n ]+ num 吧 ?其实这种假设的情况可以被省略 ,这是因为 :
11
+
12
+ 假设第 nnn 间没有被偷 ,那么此时 dp [n ]= dp [n −1 ]dp [n ] = dp [n - 1 ]dp [n ]= dp [n −1 ] ,此时 dp [n + 1 ]= dp [n ]+ num = dp [n −1 ]+ numdp [n + 1 ] = dp [n ] + num = dp [n - 1 ] + numdp [n + 1 ]= dp [n ]+ num = dp [n −1 ]+ num ,即两种情况可以 合并为一种情况 考虑 ;
13
+ 假设第 nnn 间被偷 ,那么此时 dp [n + 1 ]= dp [n ]+ numdp [n + 1 ] = dp [n ] + numdp [n + 1 ]= dp [n ]+ num 不可取 ,因为偷了第 nnn 间就不能偷第 n + 1 n + 1 n + 1 间 。
14
+ 最终的转移方程 :
15
+ dp [n + 1 ] = max (dp [n ],dp [n - 1 ]+ num )
16
+
17
+ 初始状态 :
18
+
19
+ 前 000 间房子的最大偷窃价值为 000 ,即 dp [0 ]= 0 dp [0 ] = 0 dp [0 ]= 0 。
20
+ 返回值 :
21
+
22
+ 返回 dpdpdp 列表最后一个元素值 ,即所有房间的最大偷窃价值 。
23
+ 简化空间复杂度 :
24
+
25
+ 我们发现 dp [n ]dp [n ]dp [n ] 只与 dp [n −1 ]dp [n - 1 ]dp [n −1 ] 和 dp [n −2 ]dp [n - 2 ]dp [n −2 ] 有关系 ,因此我们可以设两个变量 cur和 pre 交替记录 ,将空间复杂度降到 O (1 )O (1 )O (1 ) 。
26
+
27
+ # 简化版
28
+ class Solution :
29
+ def rob (self , nums : List [int ]) -> int :
30
+ cur , pre = 0 , 0
31
+ for num in nums :
32
+ cur , pre = max (pre + num , cur ), cur
33
+ return cur
34
+ # 标准版
35
+ class Solution :
36
+ def rob (self , nums ) -> int :
37
+ n = len (nums )
38
+ dp = [0 ]* (n + 1 )
39
+ dp [1 ] = nums [0 ]
40
+ for i in range (2 ,n + 1 ):
41
+ dp [i ] = max (dp [i - 1 ],dp [i - 2 ]+ nums [i - 1 ])
42
+ return dp [- 1 ]
43
+ # 作者:Krahets
44
+ # 链接:https://leetcode.cn/problems/house-robber/solutions/28242/da-jia-jie-she-dong-tai-gui-hua-jie-gou-hua-si-lu-/
45
+ # 来源:力扣(LeetCode)
46
+ # 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
0 commit comments