区间问题选编 maximum number of non-overlapping intervals:
按interval的end升序排序
选中集合中end最小的interval
删去所有与该interval重叠的interval(s)
重复2、3, 直到集合为空
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public int eraseOverlapIntervals (int [][] intervals) { int n=intervals.length; Arrays.sort(intervals, new Comparator <int []>() { @Override public int compare (int [] o1, int [] o2) { return o1[1 ]-o2[1 ]; } }); int count=1 ; int end=intervals[0 ][1 ]; for (int [] interval : intervals) { int start=interval[0 ]; if (start>=end){ count++; end=interval[1 ]; } } return n-count; } }
start升序、end降序
对于两个起点相同的区间,需要保证长的那个区间在上面(按照终点降序),这样才会被判定为覆盖,否则会被错误地判定为相交,少算一个覆盖区间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class LeetCode1288 { public int removeCoveredIntervals (int [][] intervals) { Arrays.sort(intervals, new Comparator <int []>() { @Override public int compare (int [] o1, int [] o2) { return o1[0 ]!=o2[0 ] ? o1[0 ]-o2[0 ] : o2[1 ]-o1[1 ]; } }); int start=intervals[0 ][0 ]; int end=intervals[0 ][1 ]; int count=-1 ; int n=intervals.length; for (int [] interval : intervals) { int left=interval[0 ]; int right=interval[1 ]; if (right<=end){ count++; }else if (left<end){ end=right; }else { start=left; end=right; } } return n-count; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class LeetCode56 { public int [][] merge(int [][] intervals) { Arrays.sort(intervals, new Comparator <int []>() { @Override public int compare (int [] o1, int [] o2) { return o1[0 ]!=o2[0 ] ? o1[0 ]-o2[0 ] : o2[1 ]-o1[1 ]; } }); List<int []> res=new ArrayList <>(); int start=intervals[0 ][0 ]; int end=intervals[0 ][1 ]; for (int i = 1 ; i < intervals.length; i++) { int left=intervals[i][0 ]; int right=intervals[i][1 ]; if (right<=end){ continue ; }else if (left<=end){ end=right; }else { res.add(new int []{start,end}); start=left; end=right; } } res.add(new int []{start,end}); int [][] array=new int [res.size()][2 ]; for (int i = 0 ; i < array.length; i++) { array[i][0 ]=res.get(i)[0 ]; array[i][1 ]=res.get(i)[1 ]; } return array; } }
两个区间集合已升序
找交集:双指针i , j
a1, a2, b1, b2
无交集:
有交集:
无论有无交集,指针都要后移:
一旦某一集合遍历完毕,则退出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class LeetCode986 { public int [][] intervalIntersection(int [][] firstList, int [][] secondList) { int n1=firstList.length; int n2=secondList.length; int i=0 ; int j=0 ; List<int []> list=new ArrayList <>(); while (i<n1 && j<n2){ int a1=firstList[i][0 ]; int a2=firstList[i][1 ]; int b1=secondList[j][0 ]; int b2=secondList[j][1 ]; if (b1<=a2 && a1<=b2){ int c1=Math.max(a1,b1); int c2=Math.min(a2,b2); list.add(new int []{c1,c2}); } if (a2<b2){ i++; }else { j++; } } int [][] res=new int [list.size()][2 ]; for (i = 0 ; i < res.length; i++) { res[i][0 ]=list.get(i)[0 ]; res[i][1 ]=list.get(i)[1 ]; } return res; } }
452. Minimum Number of Arrows to Burst Balloons 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public int findMinArrowShots (int [][] points) { Arrays.sort(points, new Comparator <int []>() { @Override public int compare (int [] o1, int [] o2) { if (o1[1 ]<=o2[1 ]){ return -1 ; }else { return 1 ; } } }); int n=points.length; int res=1 ; int start=points[0 ][0 ]; int end=points[0 ][1 ]; for (int i = 2 ; i < n; i++) { int left=points[i][0 ]; int right=points[i][1 ]; if (left>end){ start=left; end=right; res++; } } return res; }
646. Maximum Length of Pair Chain 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public int findLongestChain (int [][] pairs) { Arrays.sort(pairs,(a,b)->(a[1 ]-b[1 ])); int n=pairs.length; int end=pairs[0 ][1 ]; int res=1 ; int cur=1 ; for (int i = 1 ; i < n; i++) { int [] pair=pairs[i]; if (end<pair[0 ]){ end=pair[1 ]; cur++; res=Math.max(res,cur); } } return res; }
218. The Skyline Problem 不愧是hard题!
注意:
SortedSet去重,同一x坐标只保留一根
根据每个building,更新每个x坐标的最大高度
遍历,当最大高度改变时,则更新res
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public List<List<Integer>> getSkyline (int [][] buildings) { SortedSet<Integer> set=new TreeSet <>(); for (int [] building : buildings) { int left=building[0 ]; int right=building[1 ]; set.add(left); set.add(right); } List<Integer> edges=new ArrayList <>(set); Map<Integer,Integer> map=new HashMap <>(); for (int i = 0 ; i < edges.size(); i++) { map.put(edges.get(i),i); } int [] heights=new int [edges.size()]; for (int [] building : buildings) { int left=building[0 ]; int right=building[1 ]; int height=building[2 ]; int iLeft=map.get(left); int iRight=map.get(right); for (int i=iLeft; i<iRight; i++){ heights[i]=Math.max(heights[i],height); } } List<List<Integer>> res=new ArrayList <>(); for (int i = 0 ; i < heights.length; i++) { int cur=edges.get(i); int curHeight=heights[i]; if (res.isEmpty() || res.get(res.size()-1 ).get(1 )!=curHeight){ res.add(new ArrayList <>(Arrays.asList(cur,curHeight))); } } return res; }
759. Employee Free Time start升序、end降序
对于两个起点相同的区间,需要保证长的那个区间在上面(按照终点降序),这样才会被判定为覆盖,否则会被错误地判定为相交,少算一个覆盖区间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 public class LeetCode759 { class Interval { public int start; public int end; public Interval () {} public Interval (int _start, int _end) { start = _start; end = _end; } }; public List<Interval> employeeFreeTime (List<List<Interval>> schedule) { List<Interval> list=new ArrayList <>(); for (List<Interval> intervals : schedule) { for (Interval interval : intervals) { list.add(interval); } } Collections.sort(list,(a,b)->(a.start!=b.start ? a.start-b.start : b.end-a.end)); List<int []> work=new ArrayList <>(); int left=list.get(0 ).start; int right=list.get(0 ).end; for (int i = 1 ; i < list.size(); i++) { Interval cur=list.get(i); int start=cur.start; int end=cur.end; if (start<=right){ right=Math.max(right,end); }else { work.add(new int []{left,right}); left=start; right=end; } } work.add(new int []{left,right}); List<Interval> res=new ArrayList <>(); int start=work.get(0 )[1 ]; for (int i = 1 ; i < work.size(); i++) { int [] cur=work.get(i); res.add(new Interval (start,cur[0 ])); start=cur[1 ]; } return res; } }
1229. Meeting Scheduler 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public List<Integer> minAvailableDuration (int [][] slots1, int [][] slots2, int duration) { Arrays.sort(slots1,(a,b)->(a[0 ]-b[0 ])); Arrays.sort(slots2,(a,b)->(a[0 ]-b[0 ])); List<Integer> res=new ArrayList <>(); f:for (int [] arr1 : slots1) { for (int [] arr2 : slots2) { if (arr1[0 ]>=arr2[1 ]){ continue ; } if (arr1[1 ]<=arr2[0 ]){ break ; } int a=Math.max(arr1[0 ],arr2[0 ]); int b=Math.min(arr1[1 ],arr2[1 ]); if (b-a>=duration){ res.add(a); res.add(a+duration); break f; } } } return res; }
1272. Remove Interval 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public List<List<Integer>> removeInterval (int [][] intervals, int [] toBeRemoved) { List<List<Integer>> res=new LinkedList <>(); int left=toBeRemoved[0 ]; int right=toBeRemoved[1 ]; for (int [] interval : intervals) { int start=interval[0 ]; int end=interval[1 ]; if (start>=right || end<=left){ res.add(new LinkedList <>(Arrays.asList(start,end))); continue ; } if (start<left){ res.add(new LinkedList <>(Arrays.asList(start,left))); } if (end>right){ res.add(new LinkedList <>(Arrays.asList(right,end))); } } return res; }
435. Non-overlapping Intervals 区间问题:
non-overlapping intervals: end升序
covered intervals: start升序, end降序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public int eraseOverlapIntervals (int [][] intervals) { int count=0 ; Arrays.sort(intervals,(a,b)->(a[1 ]-b[1 ])); int right=intervals[0 ][1 ]; int n=intervals.length; for (int i = 1 ; i < n; i++) { if (intervals[i][0 ]<right){ count++; }else { right=intervals[i][1 ]; } } return count; }