There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it’s horizontal, y-coordinates don’t matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons.
An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.
Example:
Input:
[[10,16], [2,8], [1,6], [7,12]]
Output:
2
Explanation:
One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).
题中数组代表气球摆放的直径范围,只考虑x坐标,不考虑y坐标
如[10, 16]代表气球的范围从10到16,一个范围内只需要一支arrow就能把该范围所有气球都burst掉
重叠区域也是只需要一支arrow,比如[1,6]和[2,8]在2~6的任一点放arrow,这两个区间可以同时burst掉
让找出最少的arrow可以把所有区间的气球都burst掉
思路:
这种区间重叠问题,首先想到的是按起始点排序或者终点排序
(1) 按起始点排序的话,需要注意右边界的问题
比如
[1, 100]
[3, 8]
[9, 11]
显然前两个区间一个arrow就能搞定,因为第二个区间起始点3<100
但是如果不更新右边界,还是100
那么第3个区间也能判断用一个arrow搞定,但是[3,8]和[9,11]是不重叠的,必须用2个arrow
所以在有重叠区域时,要把右边界设为较短的那一方
此思路和435题类似
注意在排序比较时可以用Integer.compare, 也可以用a[0] < b[0] ? -1 : 1,
就是不能用a[0] - b[0], 因为start和end的取值范围可以是2-31,相减整数会溢出。
//19ms
public int findMinArrowShots(int[][] points) {
Arrays.sort(points,(a,b)->Integer.compare(a[0],b[0]));
int res = 1;
int end = points[0][1];
for(int[] cur : points) {
if(cur[0] <= end) {
end = Math.min(end, cur[1]);
} else {
res ++;
end = cur[1];
}
}
return res;
}
(2) 按endpoint排序
因为start 一定 < end(题目要求),所以看两个区间(x1, x2) 和 (y1, y2)是否重叠,
取决于y1 是否 < x2。
x1是派不上用场的,因为不管y1在x1的左边还是右边,只要y1 <= x2,就一定重叠,y1 > x2就一定不重叠。
只有不重叠,arrow的个数才会+1.
重叠的话,endpoint要以短的那个为准,但是既然已经按endpoint排序,前面的end一定比后面的end小,所以不需要处理。
java:
//19ms
public int findMinArrowShots(int[][] points) {
Arrays.sort(points,(a,b)->Integer.compare(a[1],b[1]));
int res = 1;
int end = points[0][1];
for(int[] cur : points) {
if(cur[0] > end) {
res ++;
end = cur[1];
}
}
return res;
}
c++
int findMinArrowShots(vector<vector<int>>& points) {
if (points.empty()) {
return 0;
}
sort(points.begin(), points.end(), [&](vector<int>& a1, vector<int>& a2) {
return a1[1] < a2[1];
});
int res = 1;
int right = points.front()[1];
for (const auto& point : points) {
if (point[0] > right) {
res ++;
right = point[1];
}
}
return res;
}