1. 程式人生 > 實用技巧 >貪心演算法之區間排程問題

貪心演算法之區間排程問題

前言

本文摘自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++。