題目
https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/
題解
重疊區間問題可以總結為在坐標軸上若干個位置為 (start(i),end(i)) 的區間,要求求解這些區間中有多少個不重疊區間,或者合并重疊的區間。
對于重疊區間問題,海外版評論區有人總結了模板,見 A Concise Template for “Overlapping Interval Problem”
該問題分兩類:第一類求重疊區間個數(leetcode 452,435),第二類求合并后的區間(leetcode 56,763)。
對于第一類問題,通常按照end排序,維護一個end變量即可。
對于第二類問題,通常按照start排序,維護一個數組,每次取最后一個數作為比較的標準。
注意按照 start 或者 end 排序兩種方式都可以求解,只是在不同情況下用其中之一代碼編寫更簡潔。
本文總結了leetcode中重疊區間問題的題目,涉及到的題目如下:
- leetcode 56 合并區間
- leetcode 452 射氣球
- leetcode 435 無重疊區間
- leetcode 763 劃分字母區間
本題思路
回到本題,思路是,維護一個小根堆,里面存 end,當 start 大于最小的 end 時,說明前面的線段和當前的線段不可能同時被切,所以把前面的線段全部一刀切。
后來發現,不需要維護小根堆,只要用一個變量維護最小值就可以了。
class Solution {public int findMinArrowShots(int[][] points
) {Arrays.sort(points
, (o1
, o2
) -> (long) o1
[0] - (long) o2
[0] > 0 ? 1 : -1);int count
= 0;long minEnd
= Long.MAX_VALUE
;for (int[] pair
: points
) {if (minEnd
!= Long.MAX_VALUE
&& pair
[0] > minEnd
) {minEnd
= Long.MAX_VALUE
;count
++;}minEnd
= Math.min(minEnd
, pair
[1]);}return count
+ 1; }
}
思路來源:左程云“最大線段重合問題”
另外,對于“求重疊最多的繩子條數”問題,見視頻 15:49
package class04_07;import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;public class Code01_CoverMax {public static int maxCover1(int[][] lines
) {int min
= Integer.MAX_VALUE
;int max
= Integer.MIN_VALUE
;for (int i
= 0; i
< lines
.length
; i
++) {min
= Math.min(min
, lines
[i
][0]);max
= Math.max(max
, lines
[i
][1]);}int cover
= 0;for (double p
= min
+ 0.5; p
< max
; p
+= 1) {int cur
= 0;for (int i
= 0; i
< lines
.length
; i
++) {if (lines
[i
][0] < p
&& lines
[i
][1] > p
) {cur
++;}}cover
= Math.max(cover
, cur
);}return cover
;}public static int maxCover2(int[][] m
) {Line[] lines
= new Line[m
.length
];for (int i
= 0; i
< m
.length
; i
++) {lines
[i
] = new Line(m
[i
][0], m
[i
][1]);}Arrays.sort(lines
, new StartComparator());PriorityQueue<Integer> heap
= new PriorityQueue<>();int max
= 0;for (int i
= 0; i
< lines
.length
; i
++) {while (!heap
.isEmpty() && heap
.peek() <= lines
[i
].start
) {heap
.poll();}heap
.add(lines
[i
].end
);max
= Math.max(max
, heap
.size());}return max
;}public static class Line {public int start
;public int end
;public Line(int s
, int e
) {start
= s
;end
= e
;}}public static class EndComparator implements Comparator<Line> {@Overridepublic int compare(Line o1
, Line o2
) {return o1
.end
- o2
.end
;}}public static int[][] generateLines(int N, int L, int R) {int size
= (int) (Math.random() * N) + 1;int[][] ans
= new int[size
][2];for (int i
= 0; i
< size
; i
++) {int a
= L + (int) (Math.random() * (R - L + 1));int b
= L + (int) (Math.random() * (R - L + 1));if (a
== b
) {b
= a
+ 1;}ans
[i
][0] = Math.min(a
, b
);ans
[i
][1] = Math.max(a
, b
);}return ans
;}public static class StartComparator implements Comparator<Line> {@Overridepublic int compare(Line o1
, Line o2
) {return o1
.start
- o2
.start
;}}public static void main(String[] args
) {Line l1
= new Line(4, 9);Line l2
= new Line(1, 4);Line l3
= new Line(7, 15);Line l4
= new Line(2, 4);Line l5
= new Line(4, 6);Line l6
= new Line(3, 7);PriorityQueue<Line> heap
= new PriorityQueue<>(new StartComparator());heap
.add(l1
);heap
.add(l2
);heap
.add(l3
);heap
.add(l4
);heap
.add(l5
);heap
.add(l6
);while (!heap
.isEmpty()) {Line cur
= heap
.poll();System.out
.println(cur
.start
+ "," + cur
.end
);}System.out
.println("test begin");int N = 100;int L = 0;int R = 200;int testTimes
= 200000;for (int i
= 0; i
< testTimes
; i
++) {int[][] lines
= generateLines(N, L, R);int ans1
= maxCover1(lines
);int ans2
= maxCover2(lines
);if (ans1
!= ans2
) {System.out
.println("Oops!");}}System.out
.println("test end");}
}
總結
以上是生活随笔為你收集整理的leetcode 452. Minimum Number of Arrows to Burst Balloons | 452. 用最少数量的箭引爆气球(左程云:最大线段重合问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。