返回

LeetCode 198:打家劫舍:动态规划与树形递归的博弈

后端

今天,我们将会深入了解 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 美元的现金。

    **结论** 

    “打家劫舍”是一个经典的动态规划和树形递归问题,它考察了我们在解决复杂问题时的技巧。通过使用这些技术,我们可以找到最优解决方案,最大限度地提高收益。所以,拿起你的工具箱,准备迎接打家劫舍的挑战吧!