1、打家劫舍
class Solution:
def rob(self, nums: List[int]) -> int:
# 初始化
if len(nums) == 0: return 0
if len(nums) == 1:
return nums[0]
# dp含义:一直偷到第i个房间的最大值为dp[i]
dp = [0]*(len(nums)+1)
# 初始化:只有一个房间,只有两个房间
dp[1], dp[2] = nums[0], max(nums[0], nums[1])
for i in range(3, len(nums)+1):
dp[i] = max(dp[i-2] + nums[i-1], dp[i-1])
return dp[-1]
2、打家劫舍II
class Solution:
def rob_normal(self, nums: List[int]) -> int:
if len(nums) == 0: return 0
if len(nums) == 1:
return nums[0]
dp = [0]*(len(nums)+1)
dp[1], dp[2] = nums[0], max(nums[0], nums[1])
for i in range(3, len(nums)+1):
dp[i] = max(dp[i-2] + nums[i-1], dp[i-1])
return dp[-1]
def rob(self, nums: List[int]) -> int:
if len(nums) == 0: return 0
if len(nums) < 3:
return max(nums)
# 围成一圈的房子有两种情况:偷第一家,偷最后一家
# 因此求出两种情况的最大值即可
result = max(self.rob_normal(nums[:-1]), self.rob_normal(nums[1:]))
return result
3、打家劫舍III
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def traversal(self, node):
# dp为一个二维数组,[0]维表示不偷当前节点的最大值,[1]维表示偷当前节点的最大值
if not node:
return [0, 0]
# 后序遍历
left_dp = self.traversal(node.left)
right_dp = self.traversal(node.right)
# 不偷当前节点,可以选择偷孩子也可以不偷,取决于偷不偷的最大值
val_0 = max(left_dp) + max(right_dp)
# 偷当前节点,值为当前节点的val加上不偷两个孩子的值
val_1 = node.val + left_dp[0] + right_dp[0]
return [val_0, val_1]
def rob(self, root: Optional[TreeNode]) -> int:
result = self.traversal(root)
return max(result)
最后一题引入了一个新的dp定义方法,即一个维度根据物品个数,一个维度根据物品状态