There are several consecutive houses along a street, each of which has some money inside. A robber wants to steal from these homes but refuses to steal from adjacent houses. The robber's capability is the maximum amount of money stolen from any single house they robbed.
You are given an integer array nums
representing the amount of money in each house (nums[i] dollars in the i-th house). You are also given an integer k
, representing the minimum number of houses the robber must steal from. Assume it's always possible to steal at least k
houses.
Return the minimum capability of the robber out of all possible ways to steal at least k
houses.
Example 1:
Input: nums = [2, 3, 5, 9], k = 2
Output: 5
Explanation: Possible ways to rob at least 2 houses:
max(nums[0], nums[2]) = 5
.max(nums[0], nums[3]) = 9
.max(nums[1], nums[3]) = 9
.
Therefore, return min(5, 9, 9) = 5
.Example 2:
Input: nums = [2, 7, 9, 3, 1], k = 2
Output: 2
Explanation: The way which leads to minimum capability is to rob the house at index 0 and 4. Return max(nums[0], nums[4]) = 2
.
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 goal is to determine the minimum capacity needed to rob a given number of houses. The brute force approach involves trying every possible combination of houses to rob, and checking if the selected houses meet the minimum house count.
Here's how the algorithm would work step-by-step:
def house_robber_brute_force(house_capacities, number_of_houses_to_rob):
number_of_houses = len(house_capacities)
minimum_maximum_stolen = float('inf')
for i in range(1 << number_of_houses):
houses_robbed = []
for j in range(number_of_houses):
if (i >> j) & 1:
houses_robbed.append(j)
number_of_houses_robbed = len(houses_robbed)
# Discard if not enough houses are robbed
if number_of_houses_robbed < number_of_houses_to_rob:
continue
adjacent_houses_robbed = False
# Checking for adjacent robbed houses
for k in range(number_of_houses_robbed - 1):
if houses_robbed[k+1] == houses_robbed[k] + 1:
adjacent_houses_robbed = True
break
# Discard if adjacent houses are robbed
if adjacent_houses_robbed:
continue
# Calculate the maximum stolen capacity for this subset
maximum_stolen = 0
for house_index in houses_robbed:
maximum_stolen = max(maximum_stolen, house_capacities[house_index])
# Update the minimum of maximum stolen amounts
minimum_maximum_stolen = min(minimum_maximum_stolen, maximum_stolen)
if minimum_maximum_stolen == float('inf'):
return -1
else:
return minimum_maximum_stolen
The best way to solve this problem is by using a guessing game based on what the smallest amount we are willing to steal could be. We then check if that amount is actually possible to steal without robbing adjacent houses, and we repeat until we find the smallest possible amount.
Here's how the algorithm would work step-by-step:
def house_robber_iv(nums, houses_to_rob):
left_bound = 0
right_bound = max(nums)
while left_bound <= right_bound:
minimum_stolen_amount = (left_bound + right_bound) // 2
# Check if robbing houses w/ min amount is possible.
if is_possible_to_rob(nums, houses_to_rob, minimum_stolen_amount):
right_bound = minimum_stolen_amount - 1
# Need to consider larger amounts next time.
else:
left_bound = minimum_stolen_amount + 1
return left_bound
def is_possible_to_rob(house_values, houses_to_rob, minimum_stolen_amount):
robbed_houses_count = 0
previous_robbed = False
for house_value in house_values:
if house_value >= minimum_stolen_amount and not previous_robbed:
robbed_houses_count += 1
previous_robbed = True
else:
previous_robbed = False
# Return if we robbed enough houses.
return robbed_houses_count >= houses_to_rob
Case | How to Handle |
---|---|
Empty input array (nums is null or has length 0) | Return 0 if k is 0, otherwise return -1 or throw an exception as robbing k houses is impossible. |
k is 0 | Return 0, as no houses need to be robbed, so no capacity is needed. |
k is greater than the number of houses that can be robbed (more than half rounded up) | Return -1 or throw an exception, as it is impossible to rob k houses under the adjacency constraint. |
Array contains only one element and k is 1 | Return the value of the single element in the array. |
All houses have the same amount of money | The binary search for capacity will still work correctly, converging to the correct minimum capacity. |
Large input array size (performance consideration) | The binary search approach will handle large arrays reasonably well with logarithmic time complexity for the search, but the feasibility check must be O(n). |
Extreme values in the input array causing integer overflow | Use long data type for calculations involving house values to prevent potential overflow. |
All house values are zero | If k > 0, return 0 because you can still rob the houses; if k==0, then return 0 as well. |