文章目录
- 前言
- 198.打家劫舍
-
- 思路
- 方法一
- 213. 打家劫舍 II
-
- 思路
- 方法一
- 337.打家劫舍 III
-
- 思路
- 方法一
- 方法二 暴力搜索和记忆化递推
- 总结
前言
198.打家劫舍
思路
非常直接的思路
dp五部曲
- dp极其下标含义:**考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。**考虑的意思是:考虑偷或者考虑不偷
- 递推公式:决定dp[i]的因素就是第i房间偷还是不偷。
如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。
如果不偷第i房间,那么dp[i] = dp[i - 1],即考 虑i-1房
然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]); - 初始化:由递推公式可以看出,基础初始化一定是dp[0]和dp[1]。所以需要初始化0和1,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即
- 遍历顺序:由于需要由前面的两项推导出来,所以一定是从前到后遍历;
方法一
考虑特殊情况
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 0: return 0
if len(nums) == 1: return nums[0]
dp = [0] * len(nums)
dp[0],dp[1] = nums[0],max(nums[0],nums[1])
for i in range(2,len(nums)):
dp[i] = max(dp[i-1],dp[i-2]+nums[i])
return dp[-1]
213. 打家劫舍 II
思路
思路非常巧妙!!💕
用下面这个图将环形的转换为线性,也就是三种情况。1. 不考虑首位 2. 不考虑尾 3. 不考虑首。其中,1可以忽略,那么就是找2和3这两个情况里面max的。
方法一
写了一个函数来反复调用
自己写的注意事项
- 注意特殊情况,别忘了
- 忘了dp的初始化💜非常不应该
- nums[0:-1]和nums[1:]表示的是不包括尾巴,和不包括head的写法,[0:-1]这个slice不包括倒数第一个元素
- 卡哥写的注意一下,他只使用两个变量,premax和currmax即可
class Solution(object):
def