给每一个house找到最近的heater,不断update result。
解法一
寻找的过程中可以发现一个规律,每一个house都是离那个最optimized的heater越来越近,然后远离。所以当radius变大后的前一个radius,就是我们要选的最optimized的那个。
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
sort(houses.begin(), houses.end());
sort(heaters.begin(), heaters.end());
int m=heaters.size();
int res=0, j=0;
for(int i: houses){
while(j+1<m && abs(i-heaters[j+1])<=abs(i-heaters[j])){
j++;
}
res = max(res, abs(i-heaters[j]));
}
return res;
}
};
优化
先假设houses的position range大于heaters,然后我们就可以分为三个部分来解决每个houses的case。
houses: | 1, 2, ... , | 9, ... , 89, | ... , 100 | --- n = houses.size();
heaters: | | 9, ... , 79 | | --- m = heaters.size();
part 1 part 2 part 3
part 1(在heaters range前): res = heaters[0]-houses[0];
part 3(在heaters range后): res = houses[n-1]-heaters[m-1];
part 2(在heaters range中间): 寻找每个houses相邻的两个heaters,
求最近距离 res = min(houses[i]-heaters[h-1], heaters[h]-houses[i])
之后可以发现其他的case其实都包含在上面讨论的三种情况中了。
Case 1: no intersection (heaters range smaller)
houses: | 6, 7, ... , | 9, ... , 89, | ... , 100 | --- n = houses.size();
heaters: | 1, 2, ... , 5 | --- m = heaters.size();
handle as part 3
Case 2: no intersection (heaters range larger)
houses: | 6, 7, ... , | 9, ... , 89, | ... , 100 | --- n = houses.size();
heaters: | 101, ... | --- m = heaters.size();
handle as part 1
Case 3: intersection
houses: | 6, 7, ... , | 9, ... , 89, | ... , 100 | --- n = houses.size();
heaters: | 1, 2, ... , 5 | 6, ... --- m = heaters.size();
no intersection 的部分可以参考case 1 and case 2, intersection 可以按照假设的case来处理。
个人觉得面试还是写优化前的吧,解释起来太费劲了。。。
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
sort(houses.begin(), houses.end());
sort(heaters.begin(), heaters.end());
int n = houses.size(), m=heaters.size();
int res = heaters[0]-houses[0];
int i=0;
// part 1
if(res>0){
while(i<n && houses[i]<=heaters[0]){
i++;
}
}else{
res = 0;
}
// part 2
int h=1;
while(i<n && houses[i]<=heaters[m-1]){
if(houses[i]>heaters[h]){
h++;
continue;
}
res = max(min(houses[i]-heaters[h-1], heaters[h]-houses[i]), res);
i++;
}
// part 3
if(i<n) res = max(res, houses[n-1]-heaters[m-1]);
return res;
}
};
解法二
用binary search来寻找最optimized
chooce: (1: sort the houses and update left/l) vs (2: without sorting houses and start with left/l=0)
--> hard to say which one is better
1
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
sort(houses.begin(), houses.end());
sort(heaters.begin(), heaters.end());
int m=heaters.size();
int res=0, l=0,r=m;
for(int t: houses){
while(l<r){
int mid = l+(r-l)/2;
if(t>heaters[mid]){
l = mid+1;
}else{
r = mid;
}
}
int dist1 = (r == m) ? INT_MAX : heaters[r] - t;
int dist2 = (r == 0) ? INT_MAX : t - heaters[r - 1];
res = max(res, min(dist1, dist2));
l = r;
r = m;
}
return res;
}
};
2
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
sort(heaters.begin(), heaters.end());
int m=heaters.size();
int res=0;
for(int t: houses){
int l=0,r=m;
while(l<r){
int mid = l+(r-l)/2;
if(t>heaters[mid]){
l = mid+1;
}else{
r = mid;
}
}
int dist1 = (r == m) ? INT_MAX : heaters[r] - t;
int dist2 = (r == 0) ? INT_MAX : t - heaters[r - 1];
res = max(res, min(dist1, dist2));
}
return res;
}
};
lower_bound 代替 binary search
class Solution {
public:
int findRadius(vector<int>& houses, vector<int>& heaters) {
sort(heaters.begin(), heaters.end());
int m=heaters.size();
int res=0;
for(int t: houses){
auto it = lower_bound(heaters.begin(), heaters.end(), t);
int dist1 = (it == heaters.end()) ? INT_MAX : *it - t;
int dist2 = (it == heaters.begin()) ? INT_MAX : t - *(it-1);
res = max(res, min(dist1, dist2));
}
return res;
}
};