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.

链接:https://leetcode.com/problems/heaters/#/description

3/28/2017

18ms, beat 96%

每个房屋只遍历一遍,heater却可能需要在update house之后重新来算。改正的次数太多。最主要的改变是:

1. radis的初始值,如果第一个house在第一个heater左边则至少大于这个距离;但是如果在heater右边,就跟其他房间/heater计算方法一样

2. 29行还是需要更新radis的,否则一旦heater前进之后,我们不会根据左边的house来更新radis的。如果左边在下一个heater范围内,一定要在更新heater index之前计算

3. 26, 29行不要逼着眼更新,一定要选跟当前radis中较大的那个

4. 注意for循环中没有步进,或者可以改成while loop

 1 public class Solution {
 2     public int findRadius(int[] houses, int[] heaters) {
 3         Arrays.sort(houses);
 4         Arrays.sort(heaters);
 5         int index = 0;
 6         int radis = 0;
 7         if (houses[0] < heaters[0]) radis = heaters[0] - houses[0];
 8         for (int i = 0; i < heaters.length; ) {
 9             // all unvisited houses left to heater[i] should be less than current radis
10             // some unvisited houses right to heater[i] may also less than current radis
11             // break when 1. invalid index, 2. houses right to heater[i] larger than current radis
12             while (index < houses.length && (houses[index] <= heaters[i] || houses[index] - heaters[i] <= radis)) index++;
13             if (index == houses.length) break;
14             // have unvisited heaters
15             // here we meet first house out of range on the right
16             if (i < heaters.length - 1) {
17                 // house is right to next heater, we could update radis when processing next heater
18                 // because this house will still break in while loop
19                 if (heaters[i + 1] <= houses[index]) {
20                     i++;
21                 } else {
22                     // next heater is right to current house, the house has to be in the range of current heater,
23                     // need to update radis
24                     // do not update heater index, we may meet more houses have to be covered by this heater
25                     if (heaters[i + 1] - houses[index] > houses[index] - heaters[i]) {
26                         radis = Math.max(houses[index] - heaters[i], radis);
27                     } else {
28                         // next heater will cover current house
29                         radis = Math.max(heaters[i + 1] - houses[index], radis);
30                         i++;
31                     }
32                     // radis determined by current house is done
33                     index++;
34                 }
35             } else {
36                 // no unvisited heaters, this last house out of range of current radis, update radis
37                 radis = houses[houses.length - 1] - heaters[i];
38                 break;
39             }
40         }
41         return radis;
42     }
43 }

还需要看别人的算法

别人的算法,巧妙的运用了Arrays.binarySearch()方法的返回值,其中第8行运用了负数的反码:(-(insertion point) - 1)。看来Java也是有意用反码,返回的是在数组中可以插入的第几个值,返回的是下标的相反数?

还有一点,如果本身返回的是正数,那么没有必要来计算,因为result = 0已经足够了。

第9,10行就是边界问题的考虑。时间复杂度O((m+n)lgn)

 1 public int findRadius(int[] houses, int[] heaters) {
 2     Arrays.sort(heaters);
 3     int result = 0;
 4     
 5     for (int house : houses) {
 6         int index = Arrays.binarySearch(heaters, house);
 7         if (index < 0) {
 8             index = ~index;
 9             int dist1 = index - 1 >= 0 ? house - heaters[index - 1] : Integer.MAX_VALUE;
10             int dist2 = index < heaters.length ? heaters[index] - house : Integer.MAX_VALUE;
11             
12             result = Math.max(result, Math.min(dist1, dist2));
13         }
14     }
15     
16     return result;
17 }

另外一种算法,还是不理解:https://discuss.leetcode.com/topic/71450/simple-java-solution-with-2-pointers

我猜测的原因是,目的是每个house都被取暖,所以按照house来遍历肯定可以保证都被cover了,而且它只跟左右的来比较

 1 public class Solution {
 2     public int findRadius(int[] houses, int[] heaters) {
 3         Arrays.sort(houses);
 4         Arrays.sort(heaters);
 5         
 6         int i = 0, res = 0;
 7         for (int house : houses) {
 8             while (i < heaters.length - 1 && heaters[i] + heaters[i + 1] <= house * 2) {
 9                 i++;
10             }
11             res = Math.max(res, Math.abs(heaters[i] - house));
12         }
13         
14         return res;
15     }
16 }

更多讨论:

https://discuss.leetcode.com/category/606/heaters

posted @ 2017-03-29 02:07  panini  阅读(284)  评论(0编辑  收藏  举报