如何用动态规划算法秒杀“打家劫舍”专题三道题?
2022-12-15 02:17:48
动态规划:“打家劫舍”专题深究
前言
动态规划是一种强大的算法设计方法,在解决特定类型的优化问题时非常有效。在“打家劫舍”专题中,我们探讨了三个经典的动态规划问题,它们共同涉及一个核心问题:如何最大化收益,同时遵守特定的限制。
198. 打家劫舍
第一个问题是最基本的,小偷从街道一端开始,可以窃取任意房屋,但不能窃取相邻房屋。解决方案使用动态规划,按顺序计算每个房屋的最大收益,最终得到最大总收益。
213. 打家劫舍 II
第二个问题与第一个类似,但增加了限制:小偷不能从街道两端同时开始。解决方案将街道分为两部分,分别计算每个部分的最大收益,然后选择收益更大的部分。
337. 打家劫舍 III
第三个问题将场景从房屋转移到一棵二叉树。小偷只能窃取节点,不能窃取相邻节点。解决方案使用动态规划,从每个节点开始,递归计算以该节点为根的子树的最大收益,最终得到整个树的最大收益。
代码示例
198. 打家劫舍
def rob(nums):
if not nums:
return 0
dp = [0] * 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
def rob(nums):
if not nums:
return 0
if len(nums) == 1:
return nums[0]
part1 = nums[0:len(nums) - 1]
part2 = nums[1:len(nums)]
max1 = rob(part1)
max2 = rob(part2)
return max(max1, max2)
337. 打家劫舍 III
def rob(root):
dp = {}
def dfs(node):
if not node:
return 0
if node in dp:
return dp[node]
val = max(node.val + dfs(node.left) + dfs(node.right), dfs(node.left) + dfs(node.right))
dp[node] = val
return val
return dfs(root)
总结
“打家劫舍”专题中的问题展示了动态规划在解决最优化问题的强大功能。通过将问题分解为重叠子问题并按顺序求解,我们能够有效地计算出最佳解决方案。
常见问题解答
-
动态规划适用于哪些类型的函数?
动态规划适用于具有最优子结构和无后效性的函数。 -
最优子结构是什么意思?
最优子结构意味着问题整体的最优解可以由其子问题的最优解组成。 -
无后效性是什么意思?
无后效性意味着子问题的最优解不受其后继子问题的影响。 -
动态规划算法的时间复杂度是多少?
动态规划算法的时间复杂度通常是子问题数量的指数,但可以利用备忘录或动态规划表来优化复杂度。 -
动态规划算法的空间复杂度是多少?
动态规划算法的空间复杂度通常是子问题的数量,但也可以利用滚动数组来优化复杂度。