House Robber
You are given an integer array nums where nums[i] represents the amount of money the ith house has. The houses are arranged in a straight line, i.e. the ith house is the neighbor of the (i-1)th and (i+1)th house.
You are planning to rob money from the houses, but you cannot rob two adjacent houses because the security system will automatically alert the police if two adjacent houses were both broken into.
Return the maximum amount of money you can rob without alerting the police.
Example 1:
Input: nums = [1,1,3,3]
Output: 4
Explanation: nums[0] + nums[2] = 1 + 3 = 4.
Example 2:
Input: nums = [2,9,8,3,6]
Output: 16
Explanation: nums[0] + nums[2] + nums[4] = 2 + 8 + 6 = 16.
Constraints:
1 <= nums.length <= 100
0 <= nums[i] <= 100
Solution
A quite trivial thought is using O(n2)O(n^2)O(n2) dp. Let dp[i]dp[i]dp[i] represents the maximum money we can rob from house 0∼n0\sim n0∼n and house nnn is robbed. Then we can get the transfer function:
dp[i]=nums[i]+maxj∈[0,i−2]dp[j]
dp[i] = nums[i] + \max_{j\in [0, i-2]} dp[j]
dp[i]=nums[i]+j∈[0,i−2]maxdp[j]
If we realize the process of get maximum by brute force, the time complexity is O(n2)O(n^2)O(n2). Some data structure can accelerate this process to O(nlogn)O(n\log n)O(nlogn). However, we can directly maintain the value of maxj∈[0,i−2]dp[j]\max_{j\in [0, i-2]} dp[j]maxj∈[0,i−2]dp[j] in linear time complexity because we use this in an ascending order.
Code
Let max1
represents maxj∈[0,i−1]dp[j]\max_{j\in [0, i-1]} dp[j]maxj∈[0,i−1]dp[j] and max2
represents maxj∈[0,i−2]dp[j]\max_{j\in [0, i-2]} dp[j]maxj∈[0,i−2]dp[j]
class Solution:
def rob(self, nums: List[int]) -> int:
max1, max2 = 0, 0
for i in range(len(nums)):
nums[i] = max(max2 + nums[i], max1)
max2 = max1
max1 = nums[i]
return nums[-1]