198.打家劫舍
class Solution:
def rob(self, nums: List[int]) -> int:
#dp[i] 在i下标范围内,可以偷盗最多dp[i]个金币
#分为偷和不偷两个状态
#初始化
if len(nums) == 0:
return 0
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])
# print(dp)
return dp[-1]
213.打家劫舍II
解题思路:将环形问题转化成线性问题(变成了198的问题)
分成两种情况:不包含第一间房间和bu'bao'h
class Solution:
def rob(self, nums: List[int]) -> int:
#将环形问题转化成线性问题
#分为两种情况
#1.不包含第一间房间,2.不包含最后一间房间
if len(nums) == 1:
return nums[0]
not_first = self.dynamic(nums[1:]) # 不包含第一间房间
not_last = self.dynamic(nums[:-1]) # 不包含最后一间房
return max(not_first,not_last)
def dynamic(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[-1]
337.打家劫舍III
解题思路:动规+二叉树
class Solution:
def rob(self, root: Optional[TreeNode]) -> int:
# method 1动规
#dp数组含分成两种情况
#dp[0] 记录不偷当前节点获得的最多金钱
#dp[1] 记录偷当前节点获得的最多金钱
max_value = self.robtree(root)
return max(max_value[0],max_value[1])
def robtree(self,cur):
#终止条件,遇到空节点,肯定不能偷,不偷就是0
if not cur:
return (0,0)
#后序遍历,通过返回值一步步从低向上推
leftdp = self.robtree(cur.left)
rightdp = self.robtree(cur.right)
#不偷当前节点,偷子节点(取决于子节点的偷于不偷的两个最大状态)
val_0 = max(leftdp[0],leftdp[1]) + max(rightdp[0],rightdp[1])
#偷当前节点,不偷子节点
val_1 = cur.val + leftdp[0] + rightdp[0]
return(val_0,val_1)