目录
198. 打家劫舍
动态规划:
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums:
return 0
size = len(nums)
if size == 1:
return nums[0]
dp = [0] * size
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, size):
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
return dp[size - 1]
213. 打家劫舍 II
我们将原数组拆成两部分
1、nums[0],num[1]...num[end-1]
2、nums[1],nums[2]...nums[end]
然后我们分别对这两个数组求最大值,这个求解过程就完全套用了【打家劫舍 I】的逻辑。
我们只需要用同样的逻辑,执行两边代码,最后求两次的最大值即可。
这里我们创建两个dp数组
dp1计算的是nums[1],nums[2]...nums[end]这个数组
dp2计算的是nums[0],nums[1]...nums[end-1]这个数组
dp1是从nums[1]开始的,所以初的前两个值
dp1[0]就等于0
dp1[1]等于nums[1]
同理,dp2是从nums[0]开始的,所以初始化的前两个值
dp2[0]就等于nums[0]
dp2[1]就等于max(nums[0],nums[1])
class Solution(object):
def rob(self, nums):
if not nums:
return 0
n = len(nums)
if n<=2:
return max(nums)
dp1 = [0 for _ in xrange(n)]
dp2 = [0 for _ in xrange(n)]
# 初始化两个dp数组,dp1是计算的是[1,end],dp2计算的是[0,end-1]
dp1[0] = 0
dp1[1] = nums[1]
dp2[0] = nums[0]
dp2[1] = max(nums[0],nums[1])
# 按照【打家劫舍 I】的转移方式执行两遍
for i in xrange(2,n):
dp1[i] = max(dp1[i-1],dp1[i-2]+nums[i])
for i in xrange(2,n-1):
dp2[i] = max(dp2[i-1],dp2[i-2]+nums[i])
return max(dp1[-1],dp2[-2])
337. 打家劫舍 III
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def rob(self, root: TreeNode) -> int:
a = self.helper(root) # a 是一个二维数组, 为root的[偷值, 不偷值]
return max(a[0], a[1]) # 返回两个值的最大值, 此值为小偷最终获得的总值
# 参数为root节点, helper方法输出一个二维数组:root节点的[偷值, 不偷值]
def helper(self, root): # 递归结束条件:root为空, 输出 [0, 0]
if not root:
return [0, 0]
left = self.helper(root.left) # left是一个二维数组, 为 root 左侧子节点的[偷值, 不偷值]
right = self.helper(root.right) # right也是一个二维数组, 为root右侧子节点的[偷值, 不偷值]
robValue = left[1] + right[1] + root.val # root 的偷值
skipValue = max(left[0], left[1]) + max(right[0], right[1]) # root 的不偷值
return [robValue, skipValue] # 输出小偷可获得的最大金额