打家劫舍

题目

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 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 。

提示:

1 <= nums.length <= 100 0 <= nums[i] <= 400

题解

解题思路

利用 动态规划 的思想。以 [2,7,9,3,1] 为例。在进门偷之前,在门口先思考一个问题:偷还是不偷。我们来看下流程:
我们先准备一个账本 list 来算算怎么偷划算,现在夜深人静,准备开始偷!

  • 路过第一家,如果我偷,那么我就有2块钱,不偷我就没有钱,那就偷!小本本记下:2,即 Math.max(2, 0)
  • 路过第二家,如果我偷,那么我就有7块钱,不偷我就有2块钱,那就偷!小本本记下:7,即 Math.max(7, 2)
  • 路过第三家,如果我偷,那么我就有11块钱,不偷我就有7块钱,那就偷!小本本记下:11,即 Math.max(11, 7)
  • 路过第四家,如果我偷,那么我就有10块钱,不偷我就有11块钱,血亏,那就不偷!小本本记下:10
  • 路过第五家,如果我偷,那么我就有12块钱,不偷我就有10块钱,那就偷!小本本记下:12,即 Math.max(12, 11) 一轮下来,小本子上记下的最后那一笔,就是我能偷到的最多的钱。
/**
 * 打家劫舍
 * @param {number[]} nums
 * @return {number}
 */
export default function(nums: number[]): number {
  if (nums.length < 3) return Math.max(...nums)
  const list: number[] = []
  list[0] = nums[0]
  list[1] = Math.max(...nums.slice(0, 2))
  for (let i = 2; i < nums.length; i++) {
    list.push(Math.max(nums[i] + list[i - 2], list[i - 1]))
  }
  return list[list.length - 1]
}
Last Updated:
Contributors: luhaifeng