原题链接:https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/ 题目大意为给你一堆气球,这些气球沿X轴方向摆放,每个气球大小可能不同,一个气球占据的区间可以表示为[Xstart,Xend],气球可以重叠摆放。一支坐标为x的箭,可以扎破所有满足 Xstart <= x <= Xend 的气球,求出最少射几支箭可以将所有气球扎破。
这道题可以采用贪心策略来解决。起先我考虑的首先选择能扎破最多气球数的箭,然后在剩下的气球中再次选择扎破最多的箭直到所有气球全扎破,但是这种选择顺序可能让气球的分布更分散,反而增加了需要射出的箭的数量。由于不同气球摆放的位置可能会有部分重叠,显然相互重叠的气球更可能被同时扎破。虽然题目中给出的表示气球的数组points看不出气球摆放的顺序,但是我们可以对points数组按一定顺序排序,即先按Xstart的大小排序,再按Xend的大小排序,对排完序的points数组,采取的贪心策略就是:从points中的第一个气球开始,遍历points数组,如果第 i 个气球和前 i-1 个气球都有重叠,则它们是可以在一次射击里被一起扎破的;直到出现某个气球与它之前的某个气球完全不重叠,表示需要射出另外一支箭。按这个策略遍历下去直到最后一个气球。代码实现如下:
1 import java.util.Arrays; 2 3 public class LeetCode452 { 4 public int findMinArrowShots(int[][] points) { 5 if (points == null || points.length == 0) 6 return 0; 7 Arrays.sort(points, (a, b) -> {return a[0] - b[0] == 0 ? a[1] - b[1] : a[0] - b[0];}); 8 int arrows = 1; 9 int endindex = points[0][1]; 10 for (int i = 1; i < points.length; i++) { 11 if (points[i][0] <= endindex) { 12 endindex = endindex < points[i][1] ? endindex : points[i][1]; 13 } else { 14 arrows++; 15 endindex = points[i][1]; 16 } 17 } 18 return arrows; 19 } 20 }
注:第7行是JDK8中用Lambda表达式来实例化一个comparator接口;算法的时间复杂度是排序O(nlgn),遍历O(n)。