方法参考labuladong的实现团灭 LeetCode 打家劫舍问题,并自己用python重写了一遍
方法一: 递归+备忘录
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 有多少户人家
nums_len = len(nums)
if nums_len == 0:
return 0
# 备忘录
mome = [-1] * nums_len
# dp[start]表示由start--->end(nums_len) 能最多打劫到多少
# 注意: start的遍历是倒着来的
def dp(start):
if start >= nums_len:
return 0
# 发现备忘录里面不是初始值的说明已经计算过了, 直接返回
elif mome[start] != -1:
return mome[start]
else:
mome[start] = max(dp(start + 1), nums[start] + dp(start + 2))
return mome[start]
# 最终要得到的是start = 0
return dp(0)
用end自顶向下的递归,要处理的临界比较繁琐了,我就没有写代码
方法二: 动态规划
start是递减的(反着来的), 需要处理的临界情况比较少
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
len_nums = len(nums)
if len_nums == 0:
return 0
# n+1和n+2是空屋子,假想的
dp = [0] * (len_nums + 2)
for i in range(len_nums-1, -1, -1):
dp[i] = max(dp[i+1], dp[i+2] + nums[i])
return dp[0]
下面的递归方法的end是递增的(顺着来的),比较好理解但是要处理的临界情况比较繁琐
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
len_nums = len(nums)
if len_nums == 0:
return 0
# 这里是用0初始化,
dp = [0] * len_nums
# 这个代码的start是顺着来的, 要处理的临界情况比较繁琐
if len_nums >= 1:
dp[0] = nums[0]
if len_nums >= 2:
dp[1] = max(nums[1], nums[0])
for i in range(2, len_nums):
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
return dp[-1]
将nums划分为两段,然后取最大的那段即可
方法: 动态规划(状态压缩)
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
len_nums = len(nums)
if len_nums == 0:
return 0
if len_nums == 1:
return nums[0]
start1 = -1
end1 = len_nums - 2
start2 = 0
end2 = len_nums - 1
def robRange(start, end):
# 第一次迭代的时候,这个是后里两个空屋子
dp_i_1 = 0
dp_i_2 = 0
dp_i = 0
for i in range(end, start, -1):
dp_i = max(dp_i_1, nums[i] + dp_i_2)
# 先更新dp_i_2 和 再更新dp_i_2
dp_i_2 = dp_i_1
dp_i_1 = dp_i
return dp_i
return max(robRange(start1, end1), robRange(start2, end2))
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def __init__(self):
self.mome = dict()
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
# 树结构的备忘录用字典来做底层结构
def dp(root):
if root == None:
return 0
# 结果在备忘录内直接返回
if root in self.mome:
return self.mome[root]
# 抢这家
do_it = root.val
if root.left != None:
do_it += dp(root.left.left) + dp(root.left.right)
if root.right != None:
do_it += dp(root.right.left) + dp(root.right.right)
# 不抢,去下家
not_do = dp(root.left) + dp(root.right);
self.mome[root] = max(do_it, not_do);
return self.mome[root]
return dp(root)