Skip to content

打家劫舍

归类动态规划

定义一个 dp 变量。

介绍

你是一个专业的小偷,计划偷窃沿街的房屋。

每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1:

输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
  偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
  偷窃到的最高金额 = 2 + 9 + 1 = 12 。

理解

假设 index 为小偷所在房屋索引。dp 为一个数组。dp[index] 代表小偷从第 1 栋到第 index + 1 栋房屋中总共能偷到的最大金额。

代码

ts

// 抢劫方式一,后从往前抢
function rob (nums: number[]) {
  const dp = [] as any
  for(let i = nums.length - 1; i >= 0; i --) {
    const robNow = nums[i] + (dp[i + 2] || 0)
    const robNext = dp[i + 1] || 0
    dp[i] = Math.max(robNow, robNext)
  }
  return dp[0]
}

// 抢劫方式二,从前往后抢
function rob2 (nums: number[]) {
  const dp = [] as number[]
  for (let index = 0; index < nums.length; index ++) {
    // 如果要抢当前房屋
    const robNow = nums[index] + (dp[index - 2] || 0)
    // 如果不抢当前房屋
    const notRobNow = dp[index - 1] || 0
    // dp[index] 代表从第一间房屋抢到第 index + 1 间房屋能抢到的最大金额。
    dp[index] = Math.max(robNow, notRobNow)
  }
  return dp[nums.length - 1]
}

// in-source test suites
if (import.meta.vitest) {
  const { it, expect } = import.meta.vitest
  
  it('test', () => {
    const input = [2,7,9,3,1]
    expect(rob(input)).toBe(12)
    expect(rob([1,2,3,1])).toBe(4)
  })  
  it('test2', () => {
    const input = [2,7,9,3,1]
    expect(rob2(input)).toBe(12)
    expect(rob2([1,2,3,1])).toBe(4)
  }) 
}

Released under the MIT License.