[LeetCode] 198. House Robber(小偷)
-
Difficulty: Easy
-
Related Topics: Dynamic Programming
Description
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contract the police if two adjacent houses were broken into the same night.
你是一个专业的小偷,计划偷一整条街上所有的房子。每间房子都有一定数量的钱,唯一阻挡你偷家的障碍是每两家之间连着报警系统,如果两座相邻的房间在同一晚被偷则会立刻报警。
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rub tonight without alerting the police.
给一个非负数的整数列表来代表每间房的钱的数量,求解小偷在不惊动警察的情况下的最大收益。
Examples
Example 1
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2
Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.
Constraints
-
0 <= nums.length <= 100
-
0 <= nums[i] <= 400
Solution
这题的一个比较 naive 的想法是间隔取值,但这种方法并不奏效,比如当输入为 [1, 0, 0, 1]
时,最大收益应该是 2 而非 1。这时候需要考虑以下情况:假设 rob(i)
表示此小偷偷第 i
家时的最大收益,那么,rob(i)
的值可能有以下两种情况:
-
小偷选择偷第
i
家,此时收益为nums[i] + rob(i - 2)
(因为偷了第i
家就同时表示放弃第i - 1
家) -
小偷选择不偷第
i
家,那么收益为rob(i - 1)
两种情况取最大值即为所求。可以使用动态规划法求解,状态方程即为上面两种情况的最大值,代码如下:
import kotlin.math.max
class Solution {
fun rob(nums: IntArray): Int {
if (nums.size < 3) {
return nums.max()?:0
}
val dp = IntArray(nums.size)
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for (i in 2..nums.lastIndex) {
dp[i] = max(
nums[i] + dp[i - 2],
dp[i - 1]
)
}
return dp.last()
}
}