代码随想录算法训练营第四十天|(打家劫舍)198.打家劫舍 、 213.打家劫舍II、337.打家劫舍III

打家劫舍问题的思路:代码随想录

dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]

递推公式:dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])

初始化:dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1])

198. 打家劫舍

python 复制代码
class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]

        dp = [0 for _ in range(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]

213. 打家劫舍 II

此题不用dp数组来记录前面的状态,用pre_max和curr_max来记录

python 复制代码
class Solution:
    def robRange(self, nums, start, end):
        if end == start:
            return nums[start]
        
        pre_max = nums[start]
        curr_max = max(nums[start + 1], nums[start])

        for i in range(start + 2, end + 1):
            temp = curr_max
            curr_max = max(pre_max + nums[i], curr_max)
            pre_max = temp
        
        return curr_max

    def rob(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]
        
        result1 = self.robRange(nums, 0, len(nums)-2)
        result2 = self.robRange(nums, 1, len(nums) - 1 )        
        return max(result1, result2)

337. 打家劫舍 III

方法一:暴力递归(超出时间限制)

python 复制代码
# 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:
        if root is None:
            return 0
        if root.left is None and root.right is None:
            return root.val
        
        #偷父节点
        val1 = root.val
        if root.left:
            val1 += self.rob(root.left.left) + self.rob(root.left.right)
        if root.right:
            val1 += self.rob(root.right.left) + self.rob(root.right.right)

        #不偷父节点
        val2 = self.rob(root.left) + self.rob(root.right)

        return max(val1, val2)

方法二:动态规划

dp数组含义:此题中dp为一维长度为2的数组,dp[0]表示不偷当前节点时的最大值,dp[1]表示偷当前节点时的最大值。由于递归调用每一层都会传递一个新的dp数组,因此长度为2的dp数组已够用。

python 复制代码
# 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):
        if node is None:
            return (0, 0)
        
        left = self.traversal(node.left)
        right = self.traversal(node.right)

        # 不偷当前节点, 偷子节点(判断左右子节点偷/不偷最大)
        val_0 = max(left[0], left[1]) + max(right[0], right[1])

        # 偷当前节点, 不偷子节点
        val_1 = node.val + left[0] + right[0]

        return (val_0, val_1)

    def rob(self, root: Optional[TreeNode]) -> int:
         # dp数组(dp table)以及下标的含义:
        # 1. 下标为 0 记录 **不偷该节点** 所得到的的最大金钱
        # 2. 下标为 1 记录 **偷该节点** 所得到的的最大金钱
        dp = self.traversal(root)
        return max(dp)
        
相关推荐
Tiandaren15 分钟前
Selenium 4 教程:自动化 WebDriver 管理与 Cookie 提取 || 用于解决chromedriver版本不匹配问题
selenium·测试工具·算法·自动化
岁忧1 小时前
(LeetCode 面试经典 150 题 ) 11. 盛最多水的容器 (贪心+双指针)
java·c++·算法·leetcode·面试·go
chao_7891 小时前
二分查找篇——搜索旋转排序数组【LeetCode】两次二分查找
开发语言·数据结构·python·算法·leetcode
秋说3 小时前
【PTA数据结构 | C语言版】一元多项式求导
c语言·数据结构·算法
Maybyy3 小时前
力扣61.旋转链表
算法·leetcode·链表
卡卡卡卡罗特5 小时前
每日mysql
数据结构·算法
chao_7896 小时前
二分查找篇——搜索旋转排序数组【LeetCode】一次二分查找
数据结构·python·算法·leetcode·二分查找
lifallen7 小时前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
lixzest7 小时前
C++ Lambda 表达式详解
服务器·开发语言·c++·算法
EndingCoder7 小时前
搜索算法在前端的实践
前端·算法·性能优化·状态模式·搜索算法