There are several consecutive houses along a street, each of which has some money inside. A robber wants to steal money from the homes, but he refuses to steal from adjacent homes.
The capability of the robber is the maximum amount of money he steals from one house of all the houses he robbed.
You are given an integer array nums representing how much money is stashed in each house. More formally, the i-th house from the left has nums[i] dollars.
You are also given an integer k, representing the minimum number of houses the robber will steal from. It is always possible to steal at least k houses.
Return the minimum capability of the robber out of all the possible ways to steal at least k houses.
Example:
nums = [2,3,5,9], k = 2 Output: 5
Explanation: There are three ways to rob at least 2 houses:
Rob the houses at indices 0 and 2. Capability is max(nums[0], nums[2]) = 5. Rob the houses at indices 0 and 3. Capability is max(nums[0], nums[3]) = 9. Rob the houses at indices 1 and 3. Capability is max(nums[1], nums[3]) = 9. Therefore, we return min(5, 9, 9) = 5.
Can you provide an efficient algorithm to solve this problem?
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. |