『力扣题解』区间问题

73 阅读2分钟

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

每次射箭尽量往区间的右边射,这样可以用尽可能少的箭引爆更多的气球。先按右边界排序,然后维护变量backLimit,假设某时刻有m个气球可以用一箭全射,那么只需要满足:第一个气球的右边界 >= 其余气球的左边界,然后箭从第一个气球的右边界位置处发射。第m+1个气球发现不满足了,那么更新backLimit,ans++,表示又需要一箭。

按左边界排序应该也可以,只不过遍历的顺序得倒过来。

/**
 * @param {number[][]} points
 * @return {number}
 */
var findMinArrowShots = function (points) {
  points.sort((a, b) => a[1] - b[1]);
  const len = points.length;
  let ans = 0;
  let i = 0;

  while (i < len) {
    ans++; // 箭数
    const backLimit = points[i][1];
    // 箭从backLimit位置处发射,看后面哪些气球可以被这一箭射爆
    let j = i + 1;
    while (j < len && points[j][0] <= backLimit) {
      j++;
    }
    // 不能被这一箭射爆的第一个气球
    i = j;
  }
  return ans;
};

435. 无重叠区间

方法一和上一题类似,但是求的是需要去除的区间的最小个数,何为重叠区间,就是当规定了本轮的backLimit后,左顶点 < backLimit的那些区间(顶点相连不是重叠)。

方法二则是在区间重叠时无动于衷,遇到了不重叠的区间,就更新此时的backLimit,统计了不重叠区间的个数,再用总区间数相减。

// 方法一
var eraseOverlapIntervals = function(intervals) {
    intervals.sort((a, b) => a[1] - b[1])

    let ans = 0 // 重叠区间的个数
    let backLimit
    let i = 0
    const len = intervals.length

    while (i < len) {
        backLimit = intervals[i][1]
        let j = i + 1
        while (j < len && intervals[j][0] < backLimit) {
            ans++, j++
        }
        i = j
    }
    return ans
};

// 方法二
var eraseOverlapIntervals = function(intervals) {
    if (intervals.length <= 1) return 0
    intervals.sort((a, b) => a[1] - b[1])

    let ans = 1, backLimit = intervals[0][1]
    
    for (let i = 1; i < intervals.length; i++) {
        if (intervals[i][0] >= end) {
            ans++
            backLimit = intervals[i][1]
        }
    }
    return intervals.length - ans
};

56. 合并区间

起初我还是按右边界排序,然后被[[2,3],[4,5],[6,7],[8,9],[1,10]]卡了,如果按上面的做法,前四个区间互不重叠,到第五个区间才知道,会得到错误的解,靠start = Math.min(start, intervals[i][0])也没有用。

按左边界排序,每一轮while循环都得到一个新的合并好区间,先拿出第一个区间,初始化start和end,从它的下一个区间开始,每次更新end即可。start不需要更新,因为是按左区间排序的,第一个区间的start一定最小。

var merge = function (intervals) {
  intervals.sort((a, b) => a[0] - b[0]);
  let start = 0,
    end = 0,
    i = 0;
  const ans = [];
  const len = intervals.length;

  while (i < len) {
    start = intervals[i][0];
    end = intervals[i][1];
    let j = i + 1;
    while (j < len && intervals[j][0] <= end) {
      end = Math.max(end, intervals[j][1]);
      j++;
    }
    i = j;
    ans.push([start, end]);
  }
  return ans;
};