LeetCode 475. Heaters(供暖器)

题目描述:

Winter is coming! Your first job during the contest is to design a standard heater with fixed warm radius to warm all the houses.

Now, you are given positions of houses and heaters on a horizontal line, find out minimum radius of heaters so that all houses could be covered by those heaters.

So, your input will be the positions of houses and heaters seperately, and your expected output will be the minimum radius standard of heaters.

Note:

  1. Numbers of houses and heaters you are given are non-negative and will not exceed 25000.
  2. Positions of houses and heaters you are given are non-negative and will not exceed 10^9.
  3. As long as a house is in the heaters' warm radius range, it can be warmed.
  4. All the heaters follow your radius standard and the warm radius will the same.

 

Example 1:

Input: [1,2,3],[2]
Output: 1
Explanation: The only heater was placed in the position 2, and if we use the radius 1 standard, then all the houses can be warmed.

 

Example 2:

Input: [1,2,3,4],[1,4]
Output: 1
Explanation: The two heater was placed in the position 1 and 4. We need to use radius 1 standard, then all the houses can be warmed.

 

冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。

现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径。

所以,你的输入将会是房屋和供暖器的位置。你将输出供暖器的最小加热半径。

说明:

  1. 给出的房屋和供暖器的数目是非负数且不会超过 25000。
  2. 给出的房屋和供暖器的位置均是非负数且不会超过10^9。
  3. 只要房屋位于供暖器的半径内(包括在边缘上),它就可以得到供暖。
  4. 所有供暖器都遵循你的半径标准,加热的半径也一样。

 

示例 1:

输入: [1,2,3],[2]
输出: 1
解释: 仅在位置2上有一个供暖器。如果我们将加热半径设为1,那么所有房屋就都能得到供暖。

 

示例 2:

输入: [1,2,3,4],[1,4]
输出: 1
解释: 在位置1, 4上有两个供暖器。我们需要将加热半径设为1,这样所有房屋就都能得到供暖。

 

思路:

(1)先将houses数组和heaters数组排序。

(2)然后遍历houses数组:

  • 依次取出每一个房屋i,将i按大小次序插入到heaters数组中(并非真正插入);
  • 如果i与heaters数组中的某一个元素相同,说明这个房屋i安装有供暖器,继续判断下一个房屋;
  • 如果i比heaters数组的所有元素都小,则记录i到heaters数组的第一个元素的距离;
  • 如果i比heaters数组的所有元素都大,则记录i到heaters数组的最后一个元素的距离;
  • 如果i能够按大小次序插入到heaters数组的某两个相邻元素之间,则分别计算i到左右两个元素的距离, 取最小值,只有当加热半径满足这个值,房屋i才能被左边或者右边的供暖器的加热范围覆盖;

(3)遍历完整个数组,返回记录距离当中的最小值,即供暖器最小的加热半径。

 

实现(C++):

方法1(暴力搜索):

class Solution {
public:
    int findRadius(vector<int>& houses, vector<int>& heaters) {

        sort(houses.begin(), houses.end()); //将houses数组排序
        sort(heaters.begin(), heaters.end()); //将heaters数组排序
                
        int result=0; //最小加热半径
        int distance=0; 

        for(int i=0; i<houses.size(); i++){
        
            int j=0;
            while(j<=heaters.size()-1&&heaters[j]<houses[i]) //找到第一个大于或等于房间i的供暖器
                j++;
            
            if(j==0) //如果i比heaters数组的所有元素都小
                distance=heaters[0]-houses[i];

            else if(j==heaters.size()) //如果i比heaters数组的所有元素都大
                distance=houses[i]-heaters[heaters.size()-1];
            
            else //如果i的大小在heaters数组的某两个相邻元素之间
                distance=min(heaters[j]-houses[i], houses[i]-heaters[j-1]);
            
            if(result<distance)
                result=distance;
        }

        return result;    
    }
};

提交代码,超时了。毕竟是“二分查找”下的题目,测试用例的数据量很大,暴力搜索很有可能超时。

 

方法2(二分查找):

class Solution {
    
public:
    int myBinary_Search(vector<int> &vec, int e){ 
        //二分查找:如果e比vec数组中的所有元素都小,返回-1;比vec数组中的所有元素都大,返回-2;        
         //否则返回vec数组中第一个大于或等于e的元素的位置

        int begin=0;
        int end=vec.size()-1;
        
        if(e<vec[begin])
            return -1;
        else if(e>vec[end])
            return -2;
        
        int mid;
        int location;
        while(begin<=end){
            mid=begin+(end-begin)/2;
            if(vec[mid]==e)
                return mid;
            else if(vec[mid]<e)
                begin=mid+1;
            else{
                location=mid;
                end=mid-1;
            }
        }
        return location;
    }
    
public:
    int findRadius(vector<int>& houses, vector<int>& heaters) {

        sort(houses.begin(), houses.end()); //将houses数组排序
        sort(heaters.begin(), heaters.end()); //将heaters数组排序
                
        int result=0; //最小加热半径
        int distance=0;

        for(int i=0; i<houses.size(); i++){
        
            int j=myBinary_Search(heaters, houses[i]);
            
            if(j==-1) //如果i比heaters数组的所有元素都小
                distance=heaters[0]-houses[i];
                
            
            else if(j==-2) //如果i比heaters数组的所有元素都大
                distance=houses[i]-heaters[heaters.size()-1];
            
            else { 
                if(houses[i]==heaters[j]) //如果房屋i安装有供暖器
                    continue;
                else //如果i的大小在heaters数组的某两个相邻元素之间
                    distance=min(heaters[j]-houses[i], houses[i]-heaters[j-1]);
            } 
            
            if(result<distance)
                result=distance;
        }

        return result;
    }
};

 

方法3(lower_bound()函数):

class Solution {
    
public:
    int findRadius(vector<int>& houses, vector<int>& heaters) {

        sort(houses.begin(), houses.end()); //将houses数组排序
        sort(heaters.begin(), heaters.end()); //将heaters数组排序
                
        int result=0; //最小加热半径;
        int distance=0;

        for(int i=0; i<houses.size(); i++){
 
            vector<int>::iterator j=lower_bound(heaters.begin(), heaters.end(), houses[i]); //在heaters数组中二分查找第一个大于或等于i的元素,返回其迭代器
      
            if(j==heaters.end()) //如果i比heaters数组的所有元素都大
                distance=houses[i]-heaters[heaters.size()-1];
            
            else{
                if(*j==houses[i]) //如果房屋i安装有供暖器
                    continue;
                else{
                    if(j==heaters.begin()) //如果i比heaters数组的所有元素都小
                        distance=heaters[0]-houses[i];
                    else //如果i的大小在heaters数组的某两个相邻元素之间
                         distance=min(*j-houses[i], houses[i]-*(j-1));
                }
            }
          
            if(result<distance)
                result=distance;
        }

        return result;
    }
};

lower_bound()函数也是通过二分查找实现的。只能说掌握一些常用的STL算法真的是太重要了,不仅能使代码显得更加简洁优雅,而且还能避免重复造轮子,大大提高编码效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值