算法训练 Day47

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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值