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 systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
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.
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.
1 <= nums.length <= 1000 <= nums[i] <= 400The problem of robbing houses can be thought of as making a choice at each house: either you rob it or you skip it. The base problem is that you cannot rob two consecutive houses.
We can define a recursive function robFrom(int i) which returns the maximum amount of money that can be robbed starting from house i. The decision at each house will be:
i and skip the next house i+1.i and try to rob from house i+1.This will be a naive solution with exponential time complexity, but it establishes the foundation of the problem.
n is the number of houses.n.To optimize the recursive approach, we can use memoization to store the results of the subproblems that we've already solved, preventing re-calculation and reducing the time complexity from exponential to linear.
We can reformulate the problem iteratively using a bottom-up dynamic programming approach. We'll systematically determine the best choice at each house leading up to the final decision.
We can further optimize the space complexity by realizing that at any point, we only need the last two states to make our decision.