198. 打家劫舍

题目描述

思路
"打家劫舍"是一个经典的模板题,指的就是在动态规划问题当中,在统计答案的过程中,不能选择相邻的元素 。比如,如果我们将0位置的元素放进了背包当中,那么就不能放1位置的元素了;反之,如果我们将1位置的元素放进了背包内,就意味着0位置的元素一定没有放进背包内,同时2位置的元素不能放进背包内。题目要求我们最终统计的按照"打家劫舍"的规则,能够放进背包当中的物品的最高价值。
我们使用动态规划来解决这个问题,初始化一个长度为n的数组,名为dp,使用它来记录每一个位置按照上述规则可以获得的最高金额。我们首先来分析n == 0、n == 1和n == 2的特例,显然在第0个位置,金额就是0;在n == 1时,只能取nums[0]位置的元素放进背包内,此时最高价值就是nums[0];而在n == 2时,就需要判断nums[0]和nums[1]哪个元素的价值更高,max(nums[0], nums[1])就是dp[2]的答案。
基于上述分析,我们可以推导出dp的状态转移方程,那就是dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])。转换成自然语言其实也很好理解,对于n == i的位置,该位置能够获得的最大价值要么就是dp[i - 1]的最大价值,此时不能够取n == i位置的元素,否则不满足"不能取相邻位置的元素"的题目约束;要么就是取nums[i]位置的元素,同时累加dp[i - 2]位置的价值。
Golang 题解
go
func rob(nums []int) int {
n := len(nums)
if n == 1 {
return nums[0]
} else if n == 2 {
return max(nums[0], nums[1])
}
dp := make([]int, n + 1)
dp[1], dp[2] = nums[0], max(nums[0], nums[1])
for i := 3; i <= n; i ++ {
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1])
}
return dp[n]
}