https://leetcode.com/problems/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:code
Numbers of houses and heaters you are given are non-negative and will not exceed 25000. Positions of houses and heaters you are given are non-negative and will not exceed 10^9. As long as a house is in the heaters' warm radius range, it can be warmed. 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:leetcode
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,2,3],取暖器坐标为[2],那么取暖器的加热范围半径为1就能够为全部房屋取暖了。get
解法一:超时的作法。将全部的取暖器放入一个map中,而后对每一个house,尝试在其坐标+j和-j(从1开始递增)的位置寻找取暖器(在map中搜索),若是找到,那么这个j就是这个house的最小半径。最后,对每一个house的最小半径再求最小值。这种作法虽然简单容易理解,可是性能并不高,尤为在数字较大时,很容易超时,由于每一个house都是递增+j-j的搜索取暖器。input
public int findRadius(int[] houses, int[] heaters) { Arrays.sort(houses); Arrays.sort(heaters); int posMin = houses[0] > heaters[0] ? heaters[0] : houses[0]; int posMax = houses[houses.length - 1] > heaters[heaters.length - 1] ? houses[houses.length - 1] : heaters[heaters.length - 1]; HashMap<Integer, Boolean> heaterMap = new HashMap<Integer, Boolean>(); // add to HashMap, to increase search speed. for (int i = 0; i < heaters.length; i++) { heaterMap.put(heaters[i], true); } int max = 0; for (int i = 0; i < houses.length; i++) { int pos = houses[i]; for (int j = 0; pos - j >= posMin || pos + j <= posMax; j++) { // try to search left or right, onece found, judge max and break; if (heaterMap.containsKey(pos - j)) { max = (max < j? j : max); break; } if (heaterMap.containsKey(pos + j)) { max = (max < j? j : max); break; } } } return max; }
解法二:在方法1的基础上作了优化。既然是对每一个house都+j-j的搜索,其实就是尝试在每一个house的左边和右边找到最近的取暖器,而后在左边和右边的取暖器中找出个最小半径。最后再在全部house的最小半径中,找出一个最大值,就能够保证全部house都能取暖了。所以,这种解法,就是建立两个新数组,表示每一个house的左边和右边取暖器的坐标,这里有一个优化(我认为是一个优化,不过也能够不用这种方式),就是坐标数组里保存的都是真实坐标+1,这样,0就能够表示house的左边或者右边没有取暖器了。it
public int findRadius(int[] houses, int[] heaters) { Arrays.sort(houses); Arrays.sort(heaters); int left = 0, right = heaters.length - 1; int[] lefts = new int[houses.length]; int[] rights = new int[houses.length]; for (int i = 0; i < houses.length; i++) { while (left < heaters.length && heaters[left] <= houses[i]) { lefts[i] = left + 1; left++; } left = lefts[i] != 0 ? (lefts[i] - 1) : 0; while (right >= left && heaters[right] >= houses[i]) { rights[i] = right + 1; right--; } right = heaters.length - 1; } int ret = 0; for (int i = 0; i < houses.length; i++) { int min = Integer.MAX_VALUE; if (lefts[i] != 0) { min = Math.min(houses[i] - heaters[lefts[i] - 1], min); } if (rights[i] != 0) { min = Math.min(heaters[rights[i] - 1] - houses[i], min); } ret = Math.max(min, ret); } System.out.println(ret); return ret; }
Top解法:这是Discuss中的top解法。先将取暖器数组排序,在遍历全部house,对每一个house,在取暖器数组中进行binary search,若是命中,则说明取暖器位置和house位置重合,这个house的最小半径为0;若是没有命中,则使用返回的index,将index左边和右边的取暖器坐标与house坐标求差值,找出这个house最小半径。说白了,也是在查找house的最近左右取暖器,只是这种解法,很是清晰简单,使人佩服。
public int findRadius(int[] houses, int[] heaters) { Arrays.sort(heaters); int result = 0; for (int house : houses) { int index = Arrays.binarySearch(heaters, house); if (index < 0) { index = ~index; int dist1 = index - 1 >= 0 ? house - heaters[index - 1] : Integer.MAX_VALUE; int dist2 = index < heaters.length ? heaters[index] - house : Integer.MAX_VALUE; result = Math.max(result, Math.min(dist1, dist2)); } } return result; }
public static void main(String[] args) { Solution s = new Solution(); { int[] house = {1,2,3,4}; int[] heaters = {1,4}; assert(s.findRadius(house, heaters) == 1); } { int[] house = {1,5}; int[] heaters = {10}; assert(s.findRadius(house, heaters) == 9); } { int[] house = {1,2,3}; int[] heaters = {2}; assert(s.findRadius(house, heaters) == 1); } { int[] house = {7,9, 1}; int[] heaters = {2}; assert(s.findRadius(house, heaters) == 7); } { int[] house = {282475249,622650073,984943658,144108930,470211272,101027544,457850878,458777923}; int[] heaters = {823564440,115438165,784484492,74243042,114807987,137522503,441282327,16531729,823378840,143542612}; assert(s.findRadius(house, heaters) == 161834419); } }