代码随想录 Day - 48|#198 打家劫舍|#213 打家劫舍 II|#337 打家劫舍 III

清单

● 198.打家劫舍
● 213.打家劫舍II
● 337.打家劫舍III

LeetCode #198 打家劫舍

1. 题目

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你不触动警报装置的情况下,一夜之内能够偷窃到的最高金额

2. 思路

  1. dp[i] : 偷窃的最高金额为 i
  2. 递推公式: dp[i] = max( dp[i-2] + nums [i], dp[i-1]) ----> 局部最优解 ----> 全局最优解
  3. 初始化: 递推公式中出现i-2, 因此至少定义 dp[0] = nums[0], dp[1] = max(nums[0],nums[1])
  4. 遍历顺序: 从前往后

3. 代码实现

class Solution:
    def rob(self, nums: List[int]) -> int:
        #Special Case
        if len(nums) == 1:
            return nums[0]
        
        #Define DP
        dp = [0] * len(nums)
        
        #Initial Setting
        dp[0] = nums[0]
        dp[1] = max(nums[0],nums[1])
        
        #Cirtulation
        for i in range(2,len(nums)):
            dp[i] = max(dp[i - 2] + nums[i], dp[i-1])
        
        return dp[-1]

LeetCode #213 打家劫舍 II

1. 题目

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,今晚能够偷窃到的最高金额。

2. 思路

  1. dp[i] : 偷窃到的最高金额
  2. 递推公式: dp[i] = max( dp[i-2] + nums [i], dp[i-1]) ----> 局部最优解 ----> 全局最优解
  3. 初始化: 递推公式中出现i-2, 因此至少定义 dp[0] = nums[0], dp[1] = max(nums[0],nums[1])
  4. 遍历顺序: 从前往后

3. 代码实现

class Solution:
    def rob(self, nums: List[int]) -> int:
        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)

    def robrange(self, nums, start, end):
        if end == start:
            return nums[start]

        pre = nums[start]
        cur = max(nums[start + 1], nums[start])

        for i in range(start + 2, end + 1):
            tmp = cur
            cur = max(pre + nums[i], cur)
            pre = tmp
        
        return cur

LeetCode #337 打家劫舍 III

1. 题目

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
给定二叉树的 root。返回在不触动警报的情况下,小偷能够盗取的最高金额。

2. 思路

  1. dp数组含义: 能够盗取的最高金额
  2. 递推公式: 若选择当前节点则 val_0 = max(left[0] + left[1] + max(right[0] + right[1]), 若选择下一节点则 val_1 = node.val + left[0] + right[1]
  3. 初始化: 遇到空节点时 返回(0,0)
  4. 遍历顺序: 由于是树形结构 采用后续遍历会更好

3. 代码实现

class Solution:
    def rob(self, root: Optional[TreeNode]) -> int:
        dp = self.travel(root)
        return max(dp)

    def travel(self, node):
        if not node:
            return (0,0)

        left = self.travel(node.left)
        right = self.travel(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)

你可能感兴趣的:(python,leetcode,动态规划)