House Robber IV — Medium Problem & Solution
A robber will not rob two adjacent houses. The capability of a robbery is the largest amount taken from any single house.
- Difficulty: Medium
- Topics: Arrays, Greedy, Binary Search
- Asked at: Amazon, Google, Sprinklr
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
A robber will not rob two adjacent houses. The capability of a robbery is the largest amount taken from any single house.
Given that the robber steals from at least k houses, return the minimum possible capability.
Example 1
Input: nums = [2,3,5,9], k = 2
Output: 5
Explanation: Robbing houses 0 and 2 caps at 5.
Example 2
Input: nums = [2,7,9,3,1], k = 2
Output: 2
Explanation: Houses 0 and 4 both hold at most 2.
Example 3
Input: nums = [1,2,3,4,5,6], k = 3
Output: 5
Constraints
1 <= nums.length <= 1000001 <= nums[i] <= 10000000001 <= k <= (nums.length + 1) / 2
How to solve House Robber IV
Binary search the capability. For a fixed c, the houses holding at most c are known, and the question becomes how many non-adjacent ones can be chosen — a greedy left-to-right sweep answers it exactly.
Approach
- Search
cover[min(nums), max(nums)]. can(c): walk the array; whennums[i] <= c, take it and jump two, otherwise advance one. Feasible when at leastkhouses are taken.- Return the smallest feasible
c.
Why it works
Taking an eligible house as early as possible is optimal: any selection can be shifted left house by house without reducing its size, since skipping an eligible house only frees a slot that the next choice could have used anyway. Raising c makes more houses eligible, which can only raise the count — the monotonicity the search needs.
Complexity
- Time —
O(n log V) - Space —
O(1)
Pitfalls
- Jumping by 2 is what enforces non-adjacency; jumping by 1 after taking a house allows neighbours.
- The search range must start at the minimum, not at 0 — any capability below it admits nothing.
- This is not the classic maximum-sum House Robber; the objective is a minimax.
Reference solution
Python
from typing import List
def minCapability(nums: List[int], k: int) -> int:
lo, hi = min(nums), max(nums)
def can(cap: int) -> bool:
cnt, i = 0, 0
while i < len(nums):
if nums[i] <= cap:
cnt += 1
i += 2
else:
i += 1
return cnt >= k
while lo < hi:
mid = (lo + hi) // 2
if can(mid):
hi = mid
else:
lo = mid + 1
return loJavaScript
var minCapability = function(nums, k) {
var lo = nums[0], hi = nums[0], i;
for (i = 1; i < nums.length; i++) {
if (nums[i] < lo) lo = nums[i];
if (nums[i] > hi) hi = nums[i];
}
var can = function(cap) {
var cnt = 0, j = 0;
while (j < nums.length) {
if (nums[j] <= cap) { cnt++; j += 2; } else j++;
}
return cnt >= k;
};
while (lo < hi) {
var mid = Math.floor((lo + hi) / 2);
if (can(mid)) hi = mid; else lo = mid + 1;
}
return lo;
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.