LeetCode475. 供暖器(快速排序,二分查找)

https://leetcode-cn.com/problems/heaters/comments/

冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。
现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径。
所以,你的输入将会是房屋和供暖器的位置。你将输出供暖器的最小加热半径。
说明:
给出的房屋和供暖器的数目是非负数且不会超过 25000。
给出的房屋和供暖器的位置均是非负数且不会超过10^9。
只要房屋位于供暖器的半径内(包括在边缘上),它就可以得到供暖。
所有供暖器都遵循你的半径标准,加热的半径也一样。
示例 1:
输入: [1,2,3],[2]
输出: 1
解释: 仅在位置2上有一个供暖器。如果我们将加热半径设为1,那么所有房屋就都能得到供暖。
示例 2:
输入: [1,2,3,4],[1,4]
输出: 1
解释: 在位置1, 4上有两个供暖器。我们需要将加热半径设为1,这样所有房屋就都能得到供暖。

/*
思路:
先排序--快排
对于每个房屋,要么用前面的供暖,要么用后面的供暖,每个房屋取最小值,半径即为所有最小值中的最大值
*/

void quick_sort(int *arr,  int start, int end){
    if(start >= end){
        return;
    }
    
    int i = start;
    int j = end;
    while(i < j){
        while(arr[j] >= arr[start] && i < j){ // 先从后面走!!!
            j--;
        }
        while(arr[i] <= arr[start] && i < j){
            i++;
        }
        if(i < j){
            int tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }
    // 交换基准值
    int tmp = arr[i];
    arr[i] = arr[start];
    arr[start] = tmp;
    
    quick_sort(arr, start, i - 1);
    quick_sort(arr, i + 1, end);
}

int __binary_search(int *heaters, int len, int val, int *ret){  // 返回下标值
    int lo = 0; 
    int hi = len - 1;  // 使用对称边界

    while(lo <= hi){
        int mid = lo + (hi - lo) / 2; //找中间值
        if(val > heaters[mid]){
            lo = mid + 1;
        }
        else if(heaters[mid] == val){
            return 0;  
        }
        else if(val < heaters[mid]){
            hi = mid - 1;
        }
    }
    *ret = lo; // 如果没有找到记录中间值,此时lo>hi;
    return -1;
}

int find_min(int val, int *heaters, int heatersSize){
    int i = 0;
    bool small_flag = false;
    int small_mark = 0;
    bool big_flag = false;
    int big_mark = 0;
    
    int *ret_i = (int *)calloc(1, sizeof(int));
    int ret = __binary_search(heaters, heatersSize, val, ret_i);
    if(0 == ret) return 0;  // 判断该房子是否有供暖器,有最短为0
    if(val > heaters[0]) small_flag = true;  // 判断是否有前置供暖
    if(val < heaters[heatersSize - 1]) big_flag = true; // 判断是否有后置供暖
    small_mark = *ret_i - 1;   
    big_mark = *ret_i;
    free(ret_i);
    // 算最小半径
    int d_small = 0;
    int d_big = 0;
    if(small_flag && !big_flag){
        d_small = val - heaters[small_mark];
        return d_small;
    }
    if(!small_flag && big_flag){
        d_big = heaters[big_mark] - val;
        return d_big;
    }
    d_small = val - heaters[small_mark];
    d_big = heaters[big_mark] - val;
    
    return d_small < d_big ? d_small : d_big;
}

int findRadius(int* houses, int housesSize, int* heaters, int heatersSize) {   
    quick_sort(houses, 0 ,housesSize - 1);
    quick_sort(heaters, 0, heatersSize - 1);

    int i = 0;
    int j = 0;
    int ret = 0;
    for(; i < housesSize; i++){
        int val = find_min(houses[i], heaters, heatersSize);
        ret = ret > val ? ret : val; 
    }
    return ret; 
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值