代码随想录算法营Day44 | 198. 打家劫舍,213. 打家劫舍 II,337. 打家劫舍 III

198. 打家劫舍

这道题要求不能偷相邻的房子,那么它的动态转移公式就是dp[i] = max(dp[i-1],dp[i-2]+nums[i])即当前索引能抢的最大值就是前一个索引的值与i-2的索引的值加上当前金额的最大值。

    def rob(self, nums: List[int]) -> int:
        if len(nums) < 3:
            return max(nums)
        dp = [0] * len(nums)
        dp[0] = nums[0]
        dp[1] = max(dp[0],nums[1])
        for i in range(2,len(nums)):
            dp[i] = max(dp[i-1],dp[i-2]+nums[i])
        return dp[len(nums)-1]

213. 打家劫舍 II

这道题增加了一个条件即房子处在一个环形的街道上。这样的变形其实只要考虑第一个房子偷与被偷的两种情况,取这两种情况当中的最大值。这题我用了两个dp数组,一个记录第一个房子被偷的最大值,一个记录第一个房子不被偷的最大值。

class Solution:
    def rob(self, nums: List[int]) -> int:
        n = len(nums)
        if n < 3:
            return max(nums)
        dp = [0] * n
        dp2 = [0] * n
        dp[0] = nums[0]
        dp[1] = max(nums[1],dp[0])
        dp2[1] = nums[1]
        dp2[2] = max(dp2[1],nums[2])
        for i in range(2,n-1):
            dp[i] = max(dp[i-1],dp[i-2]+nums[i])
        for i in range(3,n):
            dp2[i] = max(dp2[i-1],dp2[i-2]+nums[i])
        return max(dp[n-2],dp2[n-1])

337. 打家劫舍 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 rob(self, root: Optional[TreeNode]) -> int:
        def help(root):
            if not root:
                return 0,0
            left = help(root.left)
            right = help(root.right)

            robval = root.val + left[0] + right[0]
            norobval = max(left[1],left[0]) + max(right[1],right[0])
            return norobval,robval
        return max(help(root))

你可能感兴趣的:(算法,数据结构,python,leetcode)