当前位置: 首页> 财经> 股票 > 代码随想录算法训练营第39天|198.打家劫舍、 213.打家劫舍II、337. 打家劫舍 III

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

时间:2025/7/13 6:26:50来源:https://blog.csdn.net/qq_43403653/article/details/142061070 浏览次数:0次

目录

  • 198.打家劫舍
    • 1、题目描述
    • 2、思路
    • 3、code
    • 4、复杂度分析
  • 213.打家劫舍II
    • 1、题目描述
    • 2、思路
    • 3、code
    • 4、复杂度分析
  • 337. 打家劫舍 III
    • 1、题目描述
    • 2、思路
    • 3、code
    • 4、复杂度分析

198.打家劫舍

题目链接:添加链接描述

1、题目描述

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

示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。

2、思路

重叠子问题: 当前房屋偷与不偷取决于 前一个房屋和前两个房屋是否被偷了

1️⃣ 确定dp数组(dp table)以及下标的含义
dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。
2️⃣ 确定递推公式
对于房屋i,有两种选择:

  • 偷:dp[i] = dp[i-2] + nums[i]
  • 不偷:dp[i] = dp[i-1]
  • d p [ i ] = m a x ( d p [ i − 2 ] + n u m s [ i ] , d p [ i − 1 ] ) dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]) dp[i]=max(dp[i2]+nums[i],dp[i1])

3️⃣ 初始化

  • dp[0] = nums[0]
  • dp[1] = max(nums[0],nums[1])

4️⃣ 遍历顺序:从前到后

3、code

class Solution:def rob(self, nums: List[int]) -> int:if len(nums) == 1:return nums[0]# dp[i] 代表偷到第i个房屋能偷窃的最高金额 i:0,,,n-1dp = [0] * len(nums) # dp[3]# 对于房屋i,有两种选择:# 偷:dp[i] = dp[i-2] + nums[i]# 不偷:dp[i] = dp[i-1]dp[0] = nums[0]dp[1] = max(nums[0],nums[1])for i in range(2,len(nums)):dp[i] = max(dp[i-2]+nums[i],dp[i-1])return dp[-1]

4、复杂度分析

1️⃣ 时间复杂度: O ( N ) O(N) O(N)
2️⃣ 空间复杂度: O ( N ) O(N) O(N)

213.打家劫舍II

题目链接:link

1、题目描述

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

示例 1:
输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

2、思路

上一道题是普通的数组,这一道题是成环的数组,如何用普通的数组来表示成环的数组?
普通的数组和成环的数组的区别就是:普通数组可以同时考虑首元素和尾元素,但是成环的数组要分为三种情况:
情况一:考虑不包含首尾元素
在这里插入图片描述
情况二:考虑包含首元素,不包含尾元素
在这里插入图片描述
情况三:考虑包含尾元素,不包含首元素
213.打家劫舍II2
🔥 考虑首元素不代表选首元素,“考虑”代表这个元素使有可能被打劫的,但是要根据动态规划的公式来判断是否打劫
情况二 和 情况三 都包含了情况一了,所以只考虑情况二和情况三就可以

3、code

class Solution:def rob(self, nums: List[int]) -> int:if len(nums) == 1:return nums[0]if len(nums) == 2:return max(nums[0],nums[1])res1 = self.robrange(0,len(nums)-2,nums)res2 = self.robrange(1,len(nums)-1,nums)return max(res1,res2)def robrange(self,start,end,nums):if start == end:return nums[start]if end - start == 1:return max(nums[start],nums[start+1])dp = [0] * (end-start+1)dp[0] = nums[start]dp[1] = max(nums[start],nums[start+1])for i in range(2,end-start+1):dp[i] = max(dp[i-1],dp[i-2]+nums[start+i])return dp[-1]

4、复杂度分析

1️⃣ 时间复杂度: O ( N ) O(N) O(N)
2️⃣ 空间复杂度: O ( N ) O(N) O(N)

337. 打家劫舍 III

题目链接:link

1、题目描述

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

2、思路

1️⃣ 对于每一个节点有两种选择,偷或者不偷

  • 偷:dp[1]
  • 不偷:dp[0]

2️⃣ 遍历终止条件:空节点,偷不偷都是0,return (0,0)

3️⃣ 后序递归
要想知道两个孩子的结果,才能计算当前偷或者不偷的结果

  • 偷当前节点:左右孩子就不能偷了
    • d p [ 1 ] = v a l + l e f t d p [ 0 ] + r i g h t d p [ 0 ] dp[1] = val + leftdp[0] + rightdp[0] dp[1]=val+leftdp[0]+rightdp[0]
  • 不偷当前节点:左右孩子可偷可不偷,选大的
    • d p [ 0 ] = m a x ( l e f t d p [ 0 ] , l e f t d p [ 1 ] ) + m a x ( r i g h t d p [ 0 ] , r i g h t d p [ 1 ] ) dp[0] = max(leftdp[0],leftdp[1]) + max(rightdp[0],rightdp[1]) dp[0]=max(leftdp[0],leftdp[1])+max(rightdp[0],rightdp[1])

3、code

# 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:res = self.travelsal(root)return max(res[0],res[1])def travelsal(self,node):# 返回两个数,分别是不选这个节点的最高金额,和选这个节点的最高金额if node is None:return (0,0)left = self.travelsal(node.left)right = self.travelsal(node.right)# 如果不选这个节点,就选左右最大值res_0 = max(left[0],left[1]) + max(right[0],right[1])# 如果选这个节点,那么子树肯定是不选的res_1 = node.val + left[0] + right[0]return (res_0,res_1)

代码递归顺序:
在这里插入图片描述

4、复杂度分析

1️⃣ 时间复杂度: O ( N ) O(N) O(N),每个节点只遍历了一次
2️⃣ 空间复杂度: O ( l o g n ) O(log n) O(logn),算上递推系统栈的空间❓

关键字:代码随想录算法训练营第39天|198.打家劫舍、 213.打家劫舍II、337. 打家劫舍 III

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: