返回

破解 LeetCode 213:环形打家劫舍的动态规划方案

前端

引言

作为一名技术娴熟的窃贼,你盯上了沿街的一圈房屋,每间都藏有可观的财宝。然而,这些房屋可不是任你轻松偷窃的,它们相互连接着防盗系统,一旦触发就会警铃大作。面对这样的挑战,你将如何制定周密的计划,最大化你的战利品?

动态规划的妙用

破解环形打家劫舍难题的关键在于动态规划。动态规划是一种强大的算法技术,用于解决可以分解成更小重叠子问题的复杂问题。在本例中,我们可以将问题分解成两个子问题:

  1. 抢劫首间房屋的最佳收益: 这需要考虑抢劫第一间房屋所能获得的收益,以及跳过第一间房屋继续抢劫后续房屋所能获得的收益。

  2. 不抢劫首间房屋的最佳收益: 这涉及跳过第一间房屋,从第二间房屋开始抢劫,并计算所能获得的最大收益。

算法流程

根据上述子问题,我们可以设计一个动态规划算法:

  1. 创建两个数组 dp1dp2,长度为 n+1n 为房屋总数)。

  2. dp1[i] 表示抢劫前 i 间房屋(包括第 i 间)的最大收益。

  3. dp2[i] 表示不抢劫第 i 间房屋(从第 i+1 间房屋开始抢劫)的最大收益。

  4. 初始化 dp1[0] = 0dp2[0] = 0,表示抢劫前 0 间房屋或不抢劫第 0 间房屋的收益均为 0。

  5. 对于 i 从 1 到 n

    • 计算 dp1[i] = max(dp2[i-1], dp1[i-2] + nums[i])
    • 计算 dp2[i] = max(dp1[i-1], dp2[i-2])
  6. 最终,max(dp1[n], dp2[n]) 即为环形打家劫舍的最大收益。

代码示例(Python)

def rob(nums):
    n = len(nums)
    if n == 0:
        return 0
    elif n == 1:
        return nums[0]

    dp1 = [0] * (n+1)
    dp2 = [0] * (n+1)

    for i in range(1, n+1):
        dp1[i] = max(dp2[i-1], dp1[i-2] + nums[i])
        dp2[i] = max(dp1[i-1], dp2[i-2])

    return max(dp1[n], dp2[n])

结论

通过运用动态规划的思想,我们可以巧妙地解决环形打家劫舍问题。这种算法能够有效地计算在环形结构中抢劫房屋的最大收益,并提供了一个清晰而高效的解决方案。掌握了动态规划的技巧,你将能自信地应对各种类似的编程挑战,并在 LeetCode 中大放异彩。