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.
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:
1 <= nums.length <= 100
0 <= nums[i] <= 400
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach for the House Robber problem is like trying every possible combination of houses you could rob. It explores each selection of houses, calculates the total loot for that selection, and then determines the best possible loot.
Here's how the algorithm would work step-by-step:
def house_robber_brute_force(house_values):
number_of_houses = len(house_values)
def rob(current_index):
# Base case: if we've reached the end, return 0
if current_index >= number_of_houses:
return 0
# Option 1: Rob the current house and skip the next
rob_current_house = house_values[current_index] + rob(current_index + 2)
# Option 2: Skip the current house and move to the next
skip_current_house = rob(current_index + 1)
# Choose the option that yields the maximum loot
return max(rob_current_house, skip_current_house)
return rob(0)
The best way to solve this problem is to think about it one house at a time and make a smart choice: rob it, or don't. We can figure out the most money we can get up to that house based on our earlier choices, without having to check every possible combination.
Here's how the algorithm would work step-by-step:
def house_robber(house_values):
number_of_houses = len(house_values)
if number_of_houses == 0:
return 0
# Store the max loot obtainable up to each house
max_loot_at_house = [0] * number_of_houses
max_loot_at_house[0] = house_values[0]
if number_of_houses > 1:
# Determine max loot up to the second house
max_loot_at_house[1] = max(house_values[0],
house_values[1])
# Build up solutions using prior results
for current_house in range(2, number_of_houses):
# Decide: rob this house, or skip it.
max_loot_robbing_current_house = house_values[current_house] +\
max_loot_at_house[current_house - 2]
# Consider not robbing the current house
max_loot_skipping_current_house = max_loot_at_house[current_house - 1]
# Storing the best choice at each stage
max_loot_at_house[current_house] = max(
max_loot_robbing_current_house,
max_loot_skipping_current_house
)
return max_loot_at_house[number_of_houses - 1]
Case | How to Handle |
---|---|
Null or empty input array | Return 0 immediately, as there's nothing to rob. |
Array with a single house | Return the value of the single house since there are no adjacent houses. |
Array with two houses | Return the maximum of the two houses' values. |
Array with all houses having zero value | Return 0, as there's no profit to be made. |
Array with all houses having the same non-zero value | The robber will pick every other house, so calculate based on array length being even or odd. |
Large input array causing potential integer overflow in intermediate calculations | Use long data type to store the maximum robbed amount. |
Array containing extreme boundary values (e.g., Integer.MAX_VALUE) | Ensure that intermediate calculations and the final result don't overflow by using long data type and carefully considering addition operations. |
Array with a mix of large and small values that causes Integer overflow when added | Use long data types for dp array to avoid overflow. |