当前位置: 首页 > wzjs >正文

wordpress 优惠券插件seo品牌优化百度资源网站推广关键词排名

wordpress 优惠券插件,seo品牌优化百度资源网站推广关键词排名,wordpress局部修改,网站建设用什么软件做题目: 198. 打家劫舍 213. 打家劫舍 II 337. 打家劫舍 III 母题:198. 打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff…

题目:

198. 打家劫舍

213. 打家劫舍 II

337. 打家劫舍 III

母题:198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

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

示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。偷窃到的最高金额 = 2 + 9 + 1 = 12 。

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 400

一、母题:打家劫舍

1.模式识别

当前房间偷不偷取决于上一个房间 》 当前状态取决于前面的状态 》 动态规划,当然打家劫舍本来就是经典动态规划题目

核心原理:当前状态 = max(打劫相邻房间, 不打劫相邻房间 + 当前房间金额)

2.母题代码实现

1.二维数组

维度1:房间

维度2:(打劫当前房间所得,不打劫当前房间所得)

即,当前状态 = max(上一个状态)

class Solution:def rob(self, nums: List[int]) -> int:n = len(nums)dp = [[0] * 2 for _ in range(n + 1)]for i, num in enumerate(nums):dp[i + 1][0] = max(dp[(i + 1) - 1])dp[i + 1][1] = dp[(i + 1) - 1][0] + numreturn max(dp[-1])

2.一维数组

当前状态 = max(上一个状态,上两个状态 + 当前节点值)

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

3.O1空间版

由于一维数组存在较强的无后效性,本题可以连数组都省去

class Solution:def rob(self, nums: List[int]) -> int:n = len(nums)prev1, prev2 = 0, 0cur = 0for num in nums:# 计算当前cur = max(prev1, prev2 + num)# 时间流逝prev1, prev2 = cur, prev1return cur

二、打家劫舍 + 循环数组

1.模式识别

当前状态 = max(打劫相邻房间, 不打劫相邻房间 + 当前房间金额)

对于类似数组这样的线性数据结构,可以通过分情况讨论来处理,

这里借用代码随想录的一段说明:代码随想录

对于一个数组,成环的话主要有如下三种情况:

  • 情况一:考虑不包含首尾元素

213.打家劫舍II

  • 情况二:考虑包含首元素,不包含尾元素

213.打家劫舍II1

  • 情况三:考虑包含尾元素,不包含首元素

213.打家劫舍II2

注意我这里用的是"考虑",例如情况三,虽然是考虑包含尾元素,但不一定要选尾部元素! 对于情况三,取nums[1] 和 nums[3]就是最大的。

而情况二 和 情况三 都包含了情况一了,所以只考虑情况二和情况三就可以了

2.代码实现

1.二维数组

class Solution:def robOne(self, nums, start, end):n = len(nums)dp = [[0, 0] for _ in range(n + 2)]for i in range(start + 2, end + 3):dp[i][0] = max(dp[i - 1])dp[i][1] = dp[i - 1][0] + nums[i - 2]return max(dp[end + 2])def rob(self, nums: List[int]) -> int:n = len(nums)if n == 1: return nums[0]ans1 = self.robOne(nums, 0, n - 2)ans2 = self.robOne(nums, 1, n - 1)return max(ans1, ans2)

2.一维数组

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

3.O1空间版

class Solution:def rob(self, nums: List[int]) -> int:n = len(nums)if n == 1: return nums[0]prev1, prev2 = 0, 0cur1 = 0for i in range(1, n):# 计算当前cur1 = max(prev1, prev2 + nums[i])# 时间流逝prev1, prev2 = cur1, prev1prev1, prev2 = 0, 0cur2 = 0for i in range(n - 1):# 计算当前cur2 = max(prev1, prev2 + nums[i])# 时间流逝prev1, prev2 = cur2, prev1return max(cur1, cur2)

三、打家劫舍 + 二叉树

1.模式识别

当前状态 = max(打劫相邻房间, 不打劫相邻房间 + 当前房间金额)

由于二叉树不是线性结构,因此不能直接套用母题模板,需要考虑遍历顺序:

本题前序、中序和层序都不可以,只有后序可以,具体原因后面详述

2.代码实现

1.二维数组

迭代:

# 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:dp0, dp1 = collections.defaultdict(int), collections.defaultdict(int)stk = [root]while stk:node = stk.pop()if node:stk.append(node)stk.append(None)if node.right: stk.append(node.right)if node.left: stk.append(node.left)else:node = stk.pop()dp1[node] = dp0[node.left] + dp0[node.right] + node.valdp0[node] = max(dp0[node.left], dp1[node.left]) + max(dp0[node.right], dp1[node.right])return max(dp0[root], dp1[root])

递归:

# 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 helper(node):if not node: return 0, 0l0, l1 = helper(node.left)r0, r1 = helper(node.right)dp0 = max(l0, l1) + max(r0, r1)dp1 = l0 + r0 + node.valreturn dp0, dp1return max(helper(root))

2.一维数组

迭代:

# 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:dp = collections.defaultdict(int)stk, node, prev = [], root, Nonewhile stk or node:while node:stk.append(node)node = node.leftnode = stk.pop()if not node.right or node.right == prev:dp0 = dp[node.left] + dp[node.right]dp1 = node.valif node.left: dp1 += dp[node.left.left] + dp[node.left.right]if node.right: dp1 += dp[node.right.left] + dp[node.right.right]dp[node] = max(dp0, dp1)prev = nodenode = Noneelse:stk.append(node)node = node.rightreturn dp[root]

递归:(记忆化搜索)

# 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:memory = {}def rob(self, root: Optional[TreeNode]) -> int:if not root: return 0if not root.left and not root.right: return root.valif root in self.memory: return self.memory[root]dp0 = self.rob(root.left) + self.rob(root.right)dp1 = root.valif root.left: dp1 += self.rob(root.left.left) + self.rob(root.left.right)if root.right: dp1 += self.rob(root.right.left) + self.rob(root.right.right)self.memory[root] = max(dp0, dp1)return self.memory[root]

3.O1空间版

二叉树不是线性结构,后序遍历有时候向上动,有时候向右动,但我估计能强行写出来,但太难写了,意义也不大

3.为什么只有后序可以?

注意打家劫舍的条件:当前状态 = max(打劫相邻房间, 不打劫相邻房间 + 当前房间金额)

即当前节点状态 = 打家劫舍函数(所有先前的相邻节点状态),

我们假设前序可以,从根节点开始,到根节点收集结果,将所有叶节点的结果算最大值

则可以写出这样的代码:

# 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:dummy1, dummy2 = TreeNode(0, root), TreeNode(0, root)parent, dp = {root: dummy1, dummy1: dummy2}, collections.defaultdict(int)ends = []stk = [root]while stk:node = stk.pop()dp0 = dp[parent[node]]dp1 = dp[parent[parent[node]]] + node.valdp[node] = max(dp0, dp1)print(node.val, dp0, dp1)if not node.left and not node.right: ends.append(node)if node.right: stk.append(node.right)parent[node.right] = nodeif node.left: stk.append(node.left)parent[node.left] = nodereturn max(dp[end] for end in ends)

这样对吗?

以题干案例为例:

很显然是不对的,口算一下前序遍历的结果是6,而后序的结果也就是案例答案7,区别在哪里呢?

其实区别也很明显,前序遍历会忽略掉右下角的1

原因分析起来也很容易,也就是考虑相邻节点则前序遍历只能考虑到从上到下一条线上的结果,无法实现全局遍历

那如果将max(根节点结果)改为sum(根节点结果)行不行呢?

也不行,算一下就会知道,由于叶节点之间不相邻,所以这么做祖先节点会被重复计算

所以只有后序遍历才可以,因为

只有后序遍历才能同时实现遍历所有节点考虑相邻状态

http://www.dtcms.com/wzjs/290421.html

相关文章:

  • 北京网站建设的价格天kol推广
  • 成都优化网站关键词杭州百度推广开户
  • 想查客户信息做网站电商网站推广方案
  • 国贸网站建设怎么在网络上推广
  • nginx 代理 wordpress网站优化外包公司
  • 酒店网站建设日程表线上宣传方式有哪些
  • 宿迁网站建设cy0001合肥网站制作
  • 免费的工程信息网站怎么推广自己的微信
  • 唯美网站建设搜索引擎优化名词解释
  • 2015年做啥网站致富廊坊百度推广seo
  • 桓台网站制作谷歌paypal官网
  • 企业网站优化怎么提高关键词排名seo是什么地方
  • 做网站月薪两万西安网站seo推广
  • 北京专业做网站公司免费b站在线观看人数在哪里找到
  • 广西建设监理协会官网站日本域名注册网站
  • 郴州市房价aso优化服务站
  • 免费 开源 企业网站长春网站优化服务
  • 设计师助理做网站吗公司在百度怎么推广
  • 购物商城类app开发短视频seo排名系统
  • 南宁市保障住房建设管理服务中心网站nba赛季排名
  • 手机可以登录国家开发银行网站吗百度软件商店
  • 新闻类网站建设二级域名和一级域名优化难度
  • 东莞网站建设电镀挂具seo导航站
  • 培训机构做网站宣传企业关键词排名优化网址
  • 会议网站建设方案百度seo报价
  • 中国建设银行网站 个人什么软件可以搜索关键词精准
  • 爱辉网站建设接外贸订单的渠道平台哪个好
  • vue 做双语版网站注册城乡规划师教材
  • 做网站asp用什么软件代写文案的软件
  • 网站搭建设计方案分销系统