返回
LeetCode 198:打家劫舍:动态规划与树形递归的博弈
后端
2024-02-23 20:43:30
今天,我们将会深入了解 LeetCode 上广受欢迎的 198 号问题:“打家劫舍”。这个问题乍看之下很简单,但它巧妙地将动态规划与树形递归相结合,考验着解决问题的技巧。
在“打家劫舍”中,小偷的目标是在不触发警报的情况下,偷取一系列房屋中尽可能多的现金。然而,有一个小小的限制:小偷不能同时偷盗相邻的两家,否则会惊动警察。
乍一看,这个问题似乎可以用贪婪算法解决,即总是偷取现金最多的一家。然而,这种方法过于简单,无法处理所有情况。为了找到最佳解决方案,我们需要使用更复杂的方法,例如动态规划或树形递归。
**动态规划**
动态规划是一种通过将问题分解为较小的子问题,然后自底向上逐步解决的方法。对于“打家劫舍”,我们可以将问题分解为:
* F(i):偷窃第 i 家房屋可以获得的最大现金数额
* F(i) = max{F(i-1), F(i-2) + nums[i]}
其中:
* F(i) 表示偷窃第 i 家房屋可以获得的最大现金数额
* F(i-1) 表示偷窃第 i-1 家房屋可以获得的最大现金数额
* F(i-2) 表示偷窃第 i-2 家房屋可以获得的最大现金数额
* nums[i] 表示第 i 家房屋中的现金数额
**树形递归**
树形递归是一种通过递归方式解决问题的方法,其中子问题相互重叠,形成一个树形结构。对于“打家劫舍”,我们可以使用树形递归来生成所有可能的偷盗方案,然后选择现金最多的方案。
树形递归的算法如下:
* rob(i):以第 i 家房屋开始偷窃的最佳方案
* rob(i) = max{rob(i+1), nums[i] + rob(i+2)}
其中:
* rob(i) 表示以第 i 家房屋开始偷窃的最佳方案
* rob(i+1) 表示以第 i+1 家房屋开始偷窃的最佳方案
* nums[i] 表示第 i 家房屋中的现金数额
**示例**
考虑以下房屋现金数组:
```
nums = [1, 2, 3, 1]
```
* **动态规划**
| i | F(i) |
|---|---|
| 1 | 1 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
最佳方案:偷窃第 1、3、4 家房屋,获得总计 5 美元的现金。
* **树形递归**
```
rob(1) = max{rob(2), 1 + rob(3)}
rob(2) = max{rob(3), 0 + rob(4)}
rob(3) = max{rob(4), 3 + rob(5)}
rob(4) = max{rob(5), 0 + rob(6)}
```
最佳方案:偷窃第 1、3、4 家房屋,获得总计 5 美元的现金。
**结论**
“打家劫舍”是一个经典的动态规划和树形递归问题,它考察了我们在解决复杂问题时的技巧。通过使用这些技术,我们可以找到最优解决方案,最大限度地提高收益。所以,拿起你的工具箱,准备迎接打家劫舍的挑战吧!