198. 打家劫舍
思路
1. dp数组定义
dp[i]: 到包括下标为i的房屋位置,所能偷窃的最大金额。
2. 确定递推公式
决定dp[i]的因素时偷不偷第i个房间。如果偷,那么不能考虑第i-1个房间,所以就看下标i-2以内的房屋所能偷的最大金额加上第i个房间的金额;如果不偷,那么可以考虑第i-1个房间,所以dp值就是dp[i-1](注意这里不一定值一定会偷第i-1个房间,只是说明我们考虑的房间可以包含第i-1个房间。) 因此,递推公式为:
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
3. 初始条件
根据递推公式,要设定dp[0]和dp[1]的值,分别为nums[0]和max(nums[0], nums[1]).
4. 遍历顺序
从前往后
5. 举例推导dp数组
代码实现
class Solution(object):
def rob(self, nums):
if len(nums) == 1:
return nums[0]
dp = [0]*len(nums)
dp[0] = nums[0]
dp[1] = 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[len(nums) - 1]
213. 打家劫舍 Ⅱ
题目链接:213. 打家劫舍 II - 力扣(LeetCode)
思路
房屋是环形,意味着不能同时去第一家和最后一家,所以就分两种情况,一种是不考虑最后一家,一种是不考虑第一家,分别按照上一题的思路求出dp数组,然后去这两种情况中dp[-1]最大的钱财数。
代码实现
class Solution(object):
def rob(self, nums):
if len(nums)== 1:
return nums[0]
if len(nums) == 2:
return max(nums[0], nums[1])
dp1 = [0] * (len(nums) - 1)
dp2 = [0] * (len(nums) - 1)
dp1[0] = nums[0]
dp1[1] = max(nums[0], nums[1])
for i in range(2, len(nums) - 1):
dp1[i] = max(dp1[i-1], dp1[i-2] + nums[i])
dp2[0] = nums[1]
dp2[1] = max(nums[1], nums[2])
for i in range(2, len(nums)-1):
dp2[i] = max(dp2[i-1], dp2[i-2] + nums[i+1])
return max(dp1[-1], dp2[-1])