475. Heaters
Problem Description
In this problem, we're given two arrays: houses
and heaters
. Each element in the houses
array represents the position of a house on a horizontal line, and each element in the heaters
array represents the position of a heater on the same line. Our objective is to find the minimum radius required for all the heaters so that every house can be covered by at least one heater's warm radius. Keep in mind that all heaters are set to the same radius, and we must choose it so every house is within the radius of at least one heater.
The goal is to minimize this radius while still ensuring that every house is within the warm range of at least one heater.
Intuition
Intuitively, we can think of this as a form of the binary search problem. We want to find the smallest radius such that every house is warm, meaning it falls within the range of [heater position - radius, heater position + radius] for at least one heater. To do this, we start by sorting both the houses
and heaters
arrays to simplify the process of checking if a house is within the warm radius of a heater.
The key insight behind the solution is to use binary search to find the minimum required radius. The binary search space is from 0 to the maximum possible distance between a house and a heater, which we initially assume to be a large number (like 10^9). We define a function check
that, given a radius value r
, determines whether all houses can be warmed with the heaters set to the specified radius.
Our binary search works as follows:
- We set
left
to 0 andright
to a large number, defining our initial search space for the radius. - We enter a loop where we continually narrow down our search space:
- We calculate the middle value
mid
betweenleft
andright
. - We call the
check
function with thismid
value to see if it's possible to cover all houses with this radius. - If
check
returnsTrue
, it means the radiusmid
is sufficient, and we might be able to find a smaller radius that also works. So we setright
tomid
to look for a potentially smaller valid radius. - If
check
returnsFalse
, it means the radiusmid
is not enough to cover all houses, so we need a larger radius. We setleft
tomid + 1
to search for a larger valid radius.
- We calculate the middle value
- When
left
is equal toright
, we have found the smallest radius that can cover all the houses.
The check
function works by iterating through each house and determining if it's within the warm radius of at least one heater.
Once we exit the binary search loop, left
will hold the minimum radius needed so that all houses are within the range of at least one heater.
Learn more about Two Pointers, Binary Search and Sorting patterns.
Solution Approach
The solution leverages the binary search algorithm to zero in on the smallest possible radius. Here are the details of the implementation steps, referencing the provided solution code:
-
Sorting Input Arrays: The problem starts with sorting both
houses
andheaters
arrays. Sorting is crucial because it allows thecheck
function to iterate over houses and heaters in order, efficiently determining if each house is covered by the current radius. -
Binary Search Setup: To find the correct radius, the code sets up a binary search with
left
as0
andright
asint(1e9)
– a large enough number to ensure it's greater than any potential radius needed. -
The
check
Function: This helper function checks whether a given radiusr
is sufficient to warm all houses. It initializes two pointers:i
for houses andj
for heaters. For each house, it checks if it falls in the range of the heater at indexj
. If not, it moves to the next heater and repeats the check. If all houses can be covered with the given radius, it returnsTrue
; otherwise,False
. -
Using Binary Search:
- A loop continues until
left
is not less thanright
, meaning the binary search space has been narrowed down to a single value. - We calculate a
mid
value as the average ofleft
andright
. Thismid
represents the potential minimum radius. - We call
check(mid)
to verify if all houses are warmed by heaters with radiusmid
.- If
True
, themid
radius is large enough, and we attempt to find a smaller minimum by settingright
tomid
. - If
False
, themid
radius is too small, so we look for a larger radius by settingleft
tomid + 1
.
- If
- A loop continues until
-
Convergence and Result: By continuously halving the search space, the binary search converges to the minimum radius required, which is then returned by the function when
left
equalsright
. This is because whencheck(mid)
can no longer find a radius that covers all houses,left
will now point to the smallest valid radius found.
The main data structure used is the sorted arrays, which enable efficient traversal. The binary search algorithm is the core pattern used to minimize the heater radius, and the check
function is an implementation of a two-pointer technique to match heaters to houses within a given warm radius. Combining sorting, binary search, and two-pointer techniques makes the solution efficient and enables it to handle a wide range of input sizes.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's say we have the following array of houses
: [1, 2, 3, 4]
, and heaters
: [1, 4]
. We want to use the solution approach to find the minimum heater radius.
-
Sorting Input Arrays:
- The
houses
array is already sorted:[1, 2, 3, 4]
. - The
heaters
array is already sorted:[1, 4]
.
- The
-
Binary Search Setup:
- We set
left
to0
andright
to10^9
(a very large number).
- We set
-
Binary Search Start
- The initial value of
left
is0
, andright
is10^9
.
- The initial value of
-
Binary Search Iteration
- First Iteration:
mid = (left + right) / 2
which calculates to(0 + 10^9) / 2 = 5 * 10^8
.- We use
check(5 * 10^8)
which will definitely returnTrue
because the radius is very large and will cover all houses. We then setright
tomid
which now becomes5 * 10^8
.
- Second Iteration:
- Now we have
left = 0
,right = 5 * 10^8
. mid = (left + right) / 2 = 2.5 * 10^8
.- Again,
check(2.5 * 10^8)
will returnTrue
. We updateright
to2.5 * 10^8
.
- Now we have
- We keep iterating, and the value of
right
will continue to decrease untilcheck
returnsFalse
, which indicates themid
value is insufficient for a heater radius.
- First Iteration:
-
Finding the Minimum Radius
- We continue the binary search to narrow down the minimum radius that can cover all houses. Assuming our houses and heaters, a
mid
of2
would be enough to cover all the houses (house at position2
is at a distance of2
from heater1
, and house at3
is also at a distance of1
from heater4
). - So, when the check function is called with
mid
values lower than2
, it will start to returnFalse
, prompting the binary search to stop decreasing theright
boundary.
- We continue the binary search to narrow down the minimum radius that can cover all houses. Assuming our houses and heaters, a
-
Arriving at the Solution
- The binary search algorithm will continue to narrow down until
left
andright
converge, giving us the minimum radius needed. - For our example, after enough iterations,
left
will equalright
at the value of2
. This means the minimum radius required for the heaters is2
.
- The binary search algorithm will continue to narrow down until
In this way, we use the binary search algorithm to efficiently find the minimum radius for the heaters to cover all houses.
Solution Implementation
1from typing import List
2
3class Solution:
4 def findRadius(self, houses: List[int], heaters: List[int]) -> int:
5 # First, sort the houses and heaters to enable efficient scanning
6 houses.sort()
7 heaters.sort()
8
9 # The function 'can_cover' checks if a given radius 'radius'
10 # is enough to cover all houses by heaters. Returns True if it is, False otherwise.
11 def can_cover(radius):
12 # Get the number of houses and heaters
13 num_houses, num_heaters = len(houses), len(heaters)
14 house_idx, heater_idx = 0, 0 # Start scanning from the first house and heater
15
16 # Iterate over all houses to check coverage
17 while house_idx < num_houses:
18 # If no more heaters are available to check, return False
19 if heater_idx >= num_heaters:
20 return False
21
22 # Calculate the minimum and maximum coverage range of the current heater
23 min_range = heaters[heater_idx] - radius
24 max_range = heaters[heater_idx] + radius
25
26 # If the current house is not covered, attempt to use the next heater
27 if houses[house_idx] < min_range:
28 return False
29 # If the current house is outside the current heater's max range,
30 # move to the next heater
31 if houses[house_idx] > max_range:
32 heater_idx += 1
33 else: # Otherwise the house is covered, move to the next house
34 house_idx += 1
35
36 return True # All houses are covered
37
38 # Start with a radius range of 0 to a large number (1e9 is given as a maximum)
39 left, right = 0, int(1e9)
40
41 # Perform a binary search to find the minimum radius
42 while left < right:
43 mid = (left + right) // 2 # Choose the middle value as the potential radius
44 # If all houses can be covered with the 'mid' radius, search the lower half
45 if can_cover(mid):
46 right = mid
47 else: # If not, search the upper half
48 left = mid + 1
49
50 # The minimum radius required to cover all houses is 'left' after the loop
51 return left
52
1class Solution {
2 public int findRadius(int[] houses, int[] heaters) {
3 // Sort the array of heaters to perform efficient searches later on
4 Arrays.sort(heaters);
5
6 // Initialize the minimum radius required for heaters to cover all houses
7 int minRadius = 0;
8
9 // Iterate through each house to find the minimum radius needed
10 for (int house : houses) {
11 // Perform a binary search to find the insertion point or the actual position of the house
12 int index = Arrays.binarySearch(heaters, house);
13
14 // If the house is not a heater, calculate the potential insert position
15 if (index < 0) {
16 index = ~index; // index = -(index + 1)
17 }
18
19 // Calculate distance to the previous heater, if any, else set to max value
20 int distanceToPreviousHeater = index > 0 ? house - heaters[index - 1] : Integer.MAX_VALUE;
21
22 // Calculate distance to the next heater, if any, else set to max value
23 int distanceToNextHeater = index < heaters.length ? heaters[index] - house : Integer.MAX_VALUE;
24
25 // Calculate the minimum distance to the closest heater for this house
26 int minDistanceToHeater = Math.min(distanceToPreviousHeater, distanceToNextHeater);
27
28 // Update the minimum radius to be the maximum of previous radii or the minimum distance for this house
29 minRadius = Math.max(minRadius, minDistanceToHeater);
30 }
31
32 // Return the minimum radius required
33 return minRadius;
34 }
35}
36
1#include <vector>
2#include <algorithm>
3
4class Solution {
5public:
6 // Function to find the minimum radius of heaters required to cover all houses.
7 int findRadius(std::vector<int>& houses, std::vector<int>& heaters) {
8 // Sort the house and heater positions to perform binary search later.
9 std::sort(houses.begin(), houses.end());
10 std::sort(heaters.begin(), heaters.end());
11
12 // Setting initial binary search range.
13 int left = 0, right = 1e9;
14
15 // Binary search to find the minimum radius.
16 while (left < right) {
17 int mid = (left + right) / 2;
18 // Check if with this radius all houses can be covered.
19 if (canCoverAllHouses(houses, heaters, mid))
20 right = mid; // Radius can be smaller or is optimal, reduce the search to left half.
21 else
22 left = mid + 1; // Radius too small, need to increase, search in right half.
23 }
24 // Once left meets right, we've found the smallest radius needed.
25 return left;
26 }
27
28 // Function to check if all houses can be covered with a given radius 'radius'.
29 bool canCoverAllHouses(const std::vector<int>& houses, const std::vector<int>& heaters, int radius) {
30 int numHouses = houses.size(), numHeaters = heaters.size();
31 int i = 0, j = 0; // Initialize pointers for houses and heaters
32
33 // Iterate over houses to check coverage.
34 while (i < numHouses) {
35 if (j >= numHeaters) return false; // Run out of heaters, can't cover all houses.
36 int minHeaterRange = heaters[j] - radius;
37 int maxHeaterRange = heaters[j] + radius;
38
39 // Current house is not covered by heater j's range.
40 if (houses[i] < minHeaterRange)
41 return false; // House i can't be covered by any heater, so return false.
42
43 // Current house is outside the range of heater j, move to next heater.
44 if (houses[i] > maxHeaterRange)
45 ++j;
46 else
47 ++i; // Current house is covered, move to the next house.
48 }
49 // All houses are covered.
50 return true;
51 }
52};
53
1function findRadius(houses: number[], heaters: number[]): number {
2 // Sort arrays to enable binary search later.
3 houses.sort((a, b) => a - b);
4 heaters.sort((a, b) => a - b);
5
6 // Initialize variables for the lengths of the houses and heaters arrays
7 const totalHouses = houses.length;
8 const totalHeaters = heaters.length;
9
10 // Initialize answer variable to store the final result, the minimum radius needed
11 let minRadius = 0;
12
13 // Initialize houseIndex and heaterIndex for traversing through the houses and heaters.
14 for (let houseIndex = 0, heaterIndex = 0; houseIndex < totalHouses; houseIndex++) {
15 // Calculate current radius for this house to the current heater
16 let currentRadius = Math.abs(houses[houseIndex] - heaters[heaterIndex]);
17
18 // Continue moving to the next heater to find the closest heater for this house
19 while (heaterIndex + 1 < totalHeaters &&
20 Math.abs(houses[houseIndex] - heaters[heaterIndex]) >= Math.abs(houses[houseIndex] - heaters[heaterIndex + 1])) {
21
22 // Keep track of the minimum radius required for the current house
23 currentRadius = Math.min(Math.abs(houses[houseIndex] - heaters[++heaterIndex]), currentRadius);
24 }
25
26 // Update the minimum radius required for all houses
27 minRadius = Math.max(currentRadius, minRadius);
28 }
29
30 // Return the minimum radius required for all houses
31 return minRadius;
32}
33
Time and Space Complexity
Time Complexity
The time complexity of the solution is determined by the following factors:
- Sorting the
houses
andheaters
arrays, which takesO(mlogm + nlogn)
time, wherem
is the number of houses andn
is the number of heaters. - The binary search to find the minimum radius, which takes
O(log(max(houses) - min(houses)))
iterations. Each iteration performs a check which has a linear pass over thehouses
andheaters
arrays, takingO(m + n)
time in the worst case. - Combining these, the overall time complexity is
O(mlogm + nlogn + (m + n)log(max(houses) - min(houses)))
.
Space Complexity
The space complexity of the solution is determined by the following factors:
- The space used to sort the
houses
andheaters
arrays, which isO(m + n)
if we consider the space used by the sorting algorithm. - The space for the variables and pointers used within the
findRadius
method and thecheck
function, which isO(1)
since it's a constant amount of space that doesn't depend on the input size.
Combining the sorting space and the constant space, the overall space complexity is O(m + n)
.
Learn more about how to find time and space complexity quickly using problem constraints.
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
Binary Search Speedrun For each of the Speedrun questions you will be given a binary search related problem and a corresponding multiple choice question The multiple choice questions are related to the techniques and template s introduced in the binary search section It's recommended that you have gone through at
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Want a Structured Path to Master System Design Too? Don’t Miss This!