LeetCode - Heaters

给每一个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;
    }   
};

猜你喜欢

转载自blog.csdn.net/real_lisa/article/details/83893888