盗亦有道:打家劫舍 III 的妙招奇思
2023-09-26 07:52:07
盗亦有道:打家劫舍 III 的妙招奇思
在夜幕降临之际,窃贼罗宾悄然潜入一户富丽堂皇的豪宅。豪宅的每一间房屋都存放着数量不等的财富,罗宾的目标是窃取尽可能多的财富,但有一个限制:他不能窃取相邻的房屋。
面对这个难题,罗宾灵机一动,想到了一个巧妙的策略。他将豪宅抽象成一棵二叉树,其中每个节点代表一间房屋,而节点的值则代表该房屋中存放的财富。罗宾需要找到一种方法,在不窃取相邻房屋的情况下,窃取到二叉树中最大的财富。
后序遍历的动态规划
罗宾决定采用后序遍历的动态规划方法来解决这个问题。后序遍历是一种遍历二叉树的经典方法,它按照以下顺序访问节点:左子树、右子树、根节点。
在后序遍历的过程中,罗宾将维护两个动态规划变量:rob
和 not_rob
。rob
表示窃取当前节点的财富,而 not_rob
表示不窃取当前节点的财富。对于每个节点,罗宾需要计算 rob
和 not_rob
的最大值,并将其存储在该节点上。
递推公式
罗宾推导出以下递推公式:
rob = max(not_rob + val, rob_left + rob_right)
not_rob = max(rob_left, rob_right)
其中:
val
是当前节点的财富。rob_left
是当前节点左子树中竊取最大财富。rob_right
是当前节点右子树中竊取最大财富。
算法步骤
基于上述递推公式,罗宾制定了以下算法步骤:
- 后序遍历二叉树。
- 对于每个节点:
- 计算
rob
和not_rob
的值。 - 将
rob
和not_rob
的最大值存储在该节点上。
- 计算
- 返回根节点的
rob
值,即为二叉树中可以窃取的最大财富。
示例
考虑以下二叉树:
10
/ \
5 15
/ \ / \
2 3 10 15
使用后序遍历的动态规划方法,我们可以计算出每个节点的 rob
和 not_rob
值,如下表所示:
节点 | val |
rob |
not_rob |
---|---|---|---|
2 | 2 | 2 | 0 |
3 | 3 | 3 | 0 |
5 | 5 | 7 | 5 |
10 | 10 | 15 | 10 |
15 | 15 | 15 | 15 |
因此,罗宾可以在不窃取相邻房屋的情况下,窃取到二叉树中的最大财富:30 元。
妙招奇思
打家劫舍 III 的解题精髓在于巧妙地利用了后序遍历和动态规划技术。后序遍历确保了罗宾在计算每个节点的 rob
和 not_rob
值时,已经掌握了其子树中的最大财富信息。动态规划则允许罗宾将复杂问题分解为一系列较小的子问题,并逐层解决。
此外,递推公式的精妙之处在于,它不仅考虑了当前节点的财富,还考虑了其子树中竊取最大财富的可能性。通过最大化 rob
和 not_rob
的值,罗宾可以找到二叉树中窃取最大财富的最佳策略。
结语
打家劫舍 III 是一道经典的动态规划问题,它考验着我们对后序遍历和动态规划技术的理解。通过深入浅出的讲解和丰富的示例,本文揭示了打家劫舍 III 的解题妙招和奇思。掌握这些技巧,我们将能够应对各种动态规划问题,从抢劫问题到背包问题,游刃有余,尽显编程之美。