House Robber#
Difficulty: Medium
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.
Constraints:
1 <= nums.length <= 100
0 <= nums[i] <= 400
Probelm Explanation:#
The problem is a classic dynamic programming challenge known as the “House Robber” problem. The scenario is that you are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, but the constraint is that adjacent houses have security systems connected. If two adjacent houses are broken into on the same night, the security systems will automatically contact the police.
The goal is to determine the maximum amount of money you can rob tonight without alerting the police. You need to find a strategy to maximize your earnings while avoiding robbing two adjacent houses.
The input to the problem is an array nums
, where nums[i]
represents the amount of money in the i
-th house. The task is to return the maximum amount of money that can be robbed without triggering the security system.
For example:
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.
The challenge involves designing an algorithm to efficiently solve this problem and find the optimal strategy for robbing houses to maximize the stolen money while adhering to the constraint of not robbing adjacent houses. The provided solution utilizes dynamic programming to achieve this.
Solution:#
Here’s a Python function to implement this algorithm:
from typing import List
class Solution:
def rob(self, nums: List[int]) -> int:
# Initialize variables to keep track of the maximum amount of money robbed at the previous and current houses
prev, curr = 0, 0
# Iterate through the houses
for n in nums:
# Calculate the maximum amount of money that can be robbed at the current house
# It is the maximum of either robbing the current house and the money robbed at the house before the previous one (prev),
# or skipping the current house and taking the maximum amount from the previous house (curr)
temp = max(n + prev, curr)
# Update the variables for the next iteration
prev, curr = curr, temp
# The final result is the maximum amount of money that can be robbed at the last house
return curr
Explanation:#
The provided code is a Python implementation of the “House Robber” problem using a dynamic programming approach. It’s part of a class Solution
and includes a method rob
that takes a list of integers nums
as input and returns the maximum amount of money that can be robbed without alerting the police.
The key idea of the algorithm is to maintain two variables, prev
and curr
, which represent the maximum amount of money that can be robbed up to the previous house and the current house, respectively. The algorithm iterates through the houses, updating these variables based on the maximum amount that can be robbed at the current house, considering the constraint of not robbing adjacent houses.
The loop calculates a temporary variable temp
that represents the maximum amount of money that can be robbed at the current house. It considers two scenarios: either robbing the current house and adding the money robbed at the house before the previous one (n + prev
), or skipping the current house and taking the maximum amount from the previous house (curr
). The maximum of these two scenarios is assigned to temp
.
The prev
and curr
variables are then updated for the next iteration. prev
is set to the previous value of curr
, and curr
is set to the calculated temp
.
The final result is the value stored in the curr
variable, representing the maximum amount of money that can be robbed at the last house. This value is returned as the result of the rob
method.
The provided test cases at the end demonstrate the usage of the rob
method with different input arrays.
Test cases:#
Here’s how you can use this solution:
# Example 1:
sol = Solution()
nums1 = [1, 2, 3, 1]
print(sol.rob(nums1)) # Output: 4
4
# Example 2:
nums2 = [2, 7, 9, 3, 1]
print(sol.rob(nums2)) # Output: 12
12
Time and Space Complexity Analysis#
Let’s analyze the time and space complexity of the provided code.
Time Complexity:#
The time complexity of the code is O(n), where n is the number of houses. The algorithm iterates through the array once, and in each iteration, it performs constant time operations. The loop runs for each house, and the number of operations inside the loop is independent of the input size. Therefore, the overall time complexity is linear, O(n).
Space Complexity:#
The space complexity is O(1), constant space. The algorithm uses only a constant amount of extra space regardless of the input size. The variables prev
, curr
, and temp
are the only additional variables used, and they do not depend on the size of the input array. Thus, the space complexity is constant, O(1).
In summary:
Time Complexity: O(n)
Space Complexity: O(1)
Challenging Exercises:#
Variation with Maximum Number of Houses to Rob: Modify the problem to include an additional constraint: you are allowed to rob at most ‘k’ houses without triggering the alarm. Find the maximum amount you can rob under this new constraint.
Robbing in a Circular Street: Extend the problem to a circular street where the first and last houses are adjacent. You cannot rob both the first and last houses simultaneously. Find the maximum amount you can rob in this circular setting.
Link to Problem: To see the House Robber problem on LeetCode, click here!