There are several consecutive houses along a street, each of which has some money inside. A robber wants to steal money from these houses, but refuses to steal from adjacent homes.
The capability of the robber is defined as the maximum amount of money he steals from one house of all the houses he robs.
You are given an integer array nums
representing the amount of money in each house (i.e., the i
-th house has nums[i]
dollars). You are also given an integer k
, representing the minimum number of houses the robber must steal from. It is 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:
nums = [2,3,5,9], k = 2
Output: 5
Explanation: 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:
nums = [2,7,9,3,1], k = 2
Output: 2
Explanation: The optimal way to rob the houses is at indices 0 and 4, leading to a capability of max(nums[0], nums[4]) = 2
.
Constraints:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9
1 <= k <= (nums.length + 1) / 2
The most straightforward approach is to generate all possible combinations of non-adjacent houses, calculate the capability for each combination, and then find the minimum capability among all combinations that include at least k
houses. This solution is highly inefficient due to the exponential number of possible combinations.
Algorithm:
Complexity Analysis:
A more efficient solution uses binary search. We can binary search the possible range of capabilities. For a given capability cap
, we can check if it's possible to rob at least k
houses such that the money stolen from each house is at most cap
. We can perform this check in linear time.
Algorithm:
nums
array. This will be the range for our binary search.capability
, check if we can rob at least k
houses such that the value of each robbed house is less than or equal to capability
.Code:
def minCapability(nums, k):
def can_rob(capability):
count = 0
robbed_prev = False
for num in nums:
if num <= capability and not robbed_prev:
count += 1
robbed_prev = True
else:
robbed_prev = False
return count >= k
left, right = min(nums), max(nums)
ans = right
while left <= right:
mid = (left + right) // 2
if can_rob(mid):
ans = mid
right = mid - 1
else:
left = mid + 1
return ans
Explanation:
The can_rob
function checks if it's possible to rob at least k
houses given a certain capability. It iterates through the houses, and if a house's value is less than or equal to the capability and we haven't robbed the previous house, we rob it and increment the count. The minCapability
function then performs a binary search to find the minimum capability that allows us to rob at least k
houses.
Complexity Analysis:
can_rob
function takes O(n) time.Edge Cases:
1 <= nums.length
, handle the case gracefully.nums
.