贪心算法之区间调度问题

前言

本文摘自labuladong

435. 无重复区间

452.用最少数量的箭引爆气球

435. 无重复区间

  1. 经典的贪心算法问题 Interval Scheduling(区间调度问题)。给你很多形如 [start, end] 的闭区间,请你设计一个算法,算出这些区间中最多有几个互不相交的区间

  2. 本题的主要思路在于贪心性质,对于所给多个闭区间,怎么才能求出互不相交的区间呢?

  3. 如:[1,3]和[3,4]或者[1,3]和[4,7]和[8,9]都是不相交的。这里的[1,3]和[3,4]也属于不相交的范围。

  • 可以先对原数组按end大小升序排序,接着定义一个x_end 为最小的end,之后再寻找start>=x_end的区间,如果有则count++,然后更新x_end=此时end。
public int intervalSchedule(int[][] intervals){
      //至少有一个区间不重复
      int count = 1;
      //按每个区间的end升序
      Arrays.sort(intervals, new Comparator<int[]>(){
            public int compare(int[] a, int[] b){
                  //由于a[1] - b[1]有溢出可能,所以用比较的方式
                  return a[1] < b[1] ? -1 : 1;
            }
      });
      //已经升序,故第一个end为最小值      
      int x_end = intervals[0][1];
      //每次start >= x_end就多一个区间,并且x_end为此时end
      for(int[] interval : intervals){
            int start = interval[0];
            if(start >= x_end){
                 count++;
                 x_end = interval[1]; 
            }
      }
      return count;
}
  • 计算出移除区间后使得剩下的都是无重复区间,不就是先把那些无重复区间计算出来,然后用区间长度去减么?

  • 那么此时只需要return n - intervalSchedule(intervals);

int eraseOverlapIntervals(int[][] intervals) {
    int n = intervals.length;
    return n - intervalSchedule(intervals);
}

452.用最少数量的箭引爆气球

  1. 本题参考435的区间调度问题,容易发现两者的输入很相似,但是有一点,当两个气球的区间边缘接触时,是可以一只箭引爆这两个气球的,所以intervalSchedule需要修改start >= 为 >。

    if(start > x_end)

  2. 这里可以理解为,本来intervalSchedule返回的count是无重复区间的个数,那么至少需要count只箭,由于区间边缘相等时可以用一只箭同时引爆两个气球,所以此时不必count++。

posted @ 2020-11-22 20:52  acchris  阅读(458)  评论(0)    收藏  举报