leetcode 475.供暖器

原题

475.供暖器
leetcode 475.供暖器_第1张图片

题解

本题需要注意的是,所给的houses和heaters数组,可能不是排过序的,因此如果算法高度依赖数组的顺序,应该在处理之前先对其进行排序;另外heater的位置并不一定是由house的地方,这一点需要注意。

方法一 暴力搜索

暴力搜索首先就是在循环遍历每个house的时候,要做好循环遍历一次hearters的准备。对于每一个house,逐个判断每个heater与house的距离的大小,直到找到后一个比前一个的距离大为止(理论上说,heaters距离house,的距离应该是先减后升的,当然如果一直减的话,那就是最后一个离得最近呗),每个house对应的距离取最大值。
本思路java代码示例:

/*
@v7fgg
执行用时:1128 ms, 在所有 Java 提交中击败了21.61%的用户
内存消耗:43.3 MB, 在所有 Java 提交中击败了11.89%的用户
2020年8月12日 14:56
*/
class Solution {
     
    public int findRadius(int[] houses, int[] heaters) {
     
        Arrays.sort(houses);
        Arrays.sort(heaters);
        int ans=0;
        for(int i=0;i<houses.length;i++){
     
            int j=1;
            for(;j<heaters.length;j++){
     
                if(Math.abs(houses[i]-heaters[j-1])<Math.abs(houses[i]-heaters[j])){
     
                    break;
                }
            }
            //之所以用的是j-1而非j+1,是因为这样可以保证j刚刚越界时,j-1不越界
            ans=Math.max(ans,Math.abs(houses[i]-heaters[j-1]));
        }
        return ans;
    }
}

上述算法重复操作太多,因为对于每一个house来说,都要从头遍历heaters。因此我们需要改进一下暴力遍历的思路:我们在已经排好序的houses和heaters里面设定指针i,初始时指向0处,每次增加i来逐步寻找离house最近的heater。而注意到,假设某个i处的heater是距离house最近的,那么下一个house的最近的heater则一定在i后边。
新思路java代码示例:

/*
@v7fgg
执行用时:11 ms, 在所有 Java 提交中击败了69.48%的用户
内存消耗:43.1 MB, 在所有 Java 提交中击败了30.77%的用户
2020年8月12日 15:46
*/
class Solution {
     
    public int findRadius(int[] houses, int[] heaters) {
     
        int ans=0;
        Arrays.sort(houses);
        Arrays.sort(heaters);
        int i=0;
        for(int house:houses){
     
            //注意>=,houses有重复的
            while(i<heaters.length-1&&Math.abs(house-heaters[i])>=Math.abs(house-heaters[i+1])){
     
                i++;
            }
            ans=Math.max(ans,Math.abs(house-heaters[i]));
        }
        return ans;
    }
}

方法二 二分法

主要思路为,通过二分找到某一个house右边大于它的第一个heater,以及此heater左边的heater,选取离得较近的那个座位取暖来源。
本思路java代码示例:

/*
@v7fgg
执行用时:19 ms, 在所有 Java 提交中击败了47.97%的用户
内存消耗:42.9 MB, 在所有 Java 提交中击败了61.54%的用户
2020年8月12日 16:31
*/
class Solution {
     
    public int findRadius(int[] houses, int[] heaters) {
     
        int ans=0;
        Arrays.sort(heaters);
        for(int house:houses){
     
            int zuo=0;
            int you=heaters.length-1;
            while(zuo<you){
     
                int mid=(zuo+you)/2;
                if(heaters[mid]<=house){
     
                    zuo=mid+1;
                }
                else{
     
                    you=mid;
                }
            }
            int l=zuo==0?1000000001:Math.abs(heaters[zuo-1]-house);
            int minDis=Math.min(l,Math.abs(heaters[zuo]-house));
            ans=Math.max(ans,minDis);
        }
        return ans;
    }
}

你可能感兴趣的:(可爱宝宝做leetcode,leetcode,java)