TARGET DECK: Leetcode FILE TAGS: Medium
Warning
Be careful when caching, since @cache requires that the input array not change in subsequent calls.
Intuition
Top Down
- Similar to House Robber, you have the choice of robbing a house or not robbing a house.
- However, since the first and last element are “adjacent to each other”, one could try the following approach in top down:
- Remove the first element, and recurse, then remove the last element bringing back in the first element, then recurse.
- That way, it is guaranteed that if one element is picked, the other element is not picked.
- The following approach does not work:
- Extend the left and right with the right element on the left and left element on the right.
- That is because you still have a chance of keeping duplicate elements.
Bottom Up
- On each iteration, store the previous house’s optimal, along with the maximum if you kept the optimal versus added to the previous previous optimal.
Complexity
Runtime
Space
- if using the bottom up approach, since we aren’t creating any new arrays.
Code
Bottom Up
class Solution:
def rob(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
pp_opt, p_opt = 0, 0
for i in range(1, n):
pp_opt, p_opt = p_opt, max(p_opt, nums[i] + pp_opt)
r1 = p_opt
pp_opt, p_opt = 0, 0
for i in range(n - 1):
pp_opt, p_opt = p_opt, max(p_opt, nums[i] + pp_opt)
r2 = p_opt
return max(r1, r2)Top Down
Array
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
def r(i):
if i < 0:
return 0
if dp[i] != -1:
return dp[i]
sr1 = nums[i] + r(i - 2)
sr2 = r(i - 1)
dp[i] = max(sr1, sr2)
return dp[i]
tmp = nums.pop()
dp = [-1] * len(nums)
r1 = r(len(nums) - 1)
nums.append(tmp)
nums.pop(0)
dp = [-1] * len(nums)
r2 = r(len(nums) - 1)
return max(r1, r2)Hashmap
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
def r(i):
if i < 0:
return 0
if i in dp:
return dp[i]
sr1 = nums[i] + r(i - 2)
sr2 = r(i - 1)
dp[i] = max(sr1, sr2)
return dp[i]
tmp = nums.pop()
dp = {}
r1 = r(len(nums) - 1)
nums.append(tmp)
nums.pop(0)
dp = {}
r2 = r(len(nums) - 1)
return max(r1, r2)Notes
Cards
START Basic Front: House Robber II Back:
END