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 109 .
  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.

解題思路

剛開始沒有想排序的問題,因爲覺得在 O(n) 的複雜度下可以完成這道題。基本思路是遍歷所有的 heaters ,找到它們兩兩之間最大的間距(當然包括一些 corner cases 的判斷,如一些heaters所在的位置在整個houses數組之外,但總體思路就是求最大的間距)然後除以2,得到最小的radius。後來掉入了無數的大坑後終於意識到自己是一個傻逼,具體掉的坑如下:

1. [1,2,3,5,15], [2,30] 最小的radius是 15 - 2 = 13,但是最大間距是 (30 - 2) / 2 = 14,顯然不是答案,原因就在於 最大間距 / 2 所得的radius最大範圍處不一定有house。像這個例子,如果 radius == 14 的話,則 2 + 14 = 16,但是在16這個位置上根本就沒有house,所以根本不需要這麼大的radius。
2. [1,5] [10] 所有heaters均在houses的位置外面時,比較也會出錯。

意識到自己的傻逼錯誤並請教過大神後,終於決定痛改前非,採用 O(nlogn) 的算法完成這道題目,具體思路如下:

  1. 先將 heaters 數組進行排序,然後對於每一個house,在已排序的 heaters 數組中利用二分搜索找到這個house的位置,如果找到了,則返回相應的下標,如果沒有找到,則以負數的形式返回這個 house 在 heaters 數組的插入位置(也就是 heaters 數組中第一個大於這個 house 的元素的下標)。
  2. 對於每個 house,比較與其相鄰的兩個heaters哪個距離這個 house 更近,如果這個更近的距離比原來已經找到的最小的 radius 大,則更新這個最小的 radius。
  3. 對一些 corner cases進行特殊的處理,如搜索到的 house 的插入位置位於已排序的 heaters 數組之外等。
  4. 二分搜索算法直接使用 Java 提供的 Arrays.binarySearch() 方法,這個方法當沒有搜索到目標元素時,將會以負數形式返回該目標元素在數組中的插入位置,這個負數形式爲 -(insert location) - 1

Java 實現代碼

class Solution {
    public int findRadius(int[] houses, int[] heaters) {
        Arrays.sort(heaters);
        int minRadius = 0;

        for (int house : houses) {
            int index = Arrays.binarySearch(heaters, house);
            int tmpRadius = 0;

            if (index < 0) {
                index = -(index + 1);

                if (index == 0) {
                    tmpRadius = heaters[0] - house;
                } else if (index >= heaters.length) {
                    tmpRadius = house - heaters[heaters.length - 1];
                } else {
                    tmpRadius = Math.min(heaters[index] - house, house - heaters[index - 1]);
                }
            }

            if (tmpRadius > minRadius) { minRadius = tmpRadius; }
        }

        return minRadius;
    }
}

在這裏我想解釋一下Java的 Arrays.binarySearch() 爲什麼要返回 -(insert location) - 1 而不是 -insert location 。這是爲了使得當所要查找的元素不在給定的數組中時,函數統一返回負數。因爲如果在查找的元素比給定數組中的所有元素都要小,則該元素在數組中的插入位置是 00 的相反數就是它自己,如果返回 -insert location 的話將會返回 0 ,此時就要對返回 0 的情況分開討論了:有可能該元素在數組中被找到了,下標是 0;但也有可能沒找到,插入位置是 0 。而通過返回 -(insert location) - 1,只要沒找到,返回的就肯定是負數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章