LeetCode算法题解
  • 关于
  • 简单

    • 1. 两数之和
    • 78. 子集
    • 141. 环形链表
    • 237. 删除链表中的节点
    • 590. N叉树的后序遍历
    • 746. 使用最小花费爬楼梯
    • 938. 二叉搜索树的范围和
    • 1025. 除数博弈
    • 1108. IP 地址无效化
    • 1221. 分割平衡字符串
    • 1281. 整数的各位积和之差
    • 1290. 二进制链表转整数
    • 1295. 统计位数为偶数的数字
    • 1431. 拥有最多糖果的孩子
    • LCP 1.猜数字
    • 面试题 17.16. 按摩师
    • 面试题53 - II. 0~n-1中缺失的数字
  • 中等

    • 3. 无重复字符的最长子串
    • 6. Z 字形变换
    • 11. 盛最多水的容器
    • 15. 三数之和
    • 17. 电话号码的字母组合
    • 22. 括号生成
    • 24. 两两交换链表中的节点
    • 39. 组合总和
    • 46. 全排列
    • 48. 旋转图像
    • 54. 螺旋矩阵
    • 55. 跳跃游戏
    • 59. 螺旋矩阵 II
    • 77. 组合
    • 94. 二叉树的中序遍历
    • 109. 有序链表转换二叉搜索树
    • 114. 二叉树展开为链表
    • 147. 对链表进行插入排序
    • 207. 课程表
    • 208. 实现 Trie (前缀树)
    • 236. 二叉树的最近公共祖先
    • 238. 除自身以外数组的乘积
    • 260. 只出现一次的数字 III
    • 319. 灯泡开关
    • 338. 比特位计数
    • 400. 第N个数字
    • 429. N叉树的层序遍历
    • 513. 找树左下角的值
    • 535.TinyURL 的加密与解密
    • 537. 复数乘法
    • 547. 朋友圈
    • 654. 最大二叉树
    • 701. 二叉搜索树中的插入操作
    • 739. 每日温度
    • 797. 所有可能的路径
    • 807. 保持城市天际线
    • 814. 二叉树剪枝
    • 877. 石子游戏
    • 921. 使括号有效的最少添加
    • 946. 验证栈序列
    • 950. 按递增顺序显示卡牌
    • 1008. 先序遍历构造二叉树
    • 1014. 最佳观光组合
    • 1161. 最大层内元素和
    • 1227. 飞机座位分配概率
    • 1282. 用户分组
    • 1305. 两棵二叉搜索树中的所有元素
    • 1315. 祖父节点值为偶数的节点和
    • 5153. 层数最深叶子节点的和
    • 面试题 16.24. 数对和
    • 面试题46. 把数字翻译成字符串
  • 困难

    • 4. 寻找两个正序数组的中位数
    • 51. N皇后
    • 57. 插入区间
    • 145. 二叉树的后序遍历
    • 239. 滑动窗口最大值
    • 297. 二叉树的序列化与反序列化
    • 980. 不同路径 III
    • 1172. 餐盘栈

题目描述

给出一个无重叠的 ,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

示例 1:

输入: intervals = [[1,3],[6,9]], newInterval = [2,5]
输出: [[1,5],[6,9]]

示例 2:

输入: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出: [[1,2],[3,10],[12,16]]
解释 这是因为新的区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠。

来源:LeetCode

思路

先找到每个点所落在的区间,如果不落在已有区间内,找到落在的区间间隔。然后根据新区间的左右端点,和所落在的区间的情况,确定一个合并区间,并把新区间落下所影响到的原区间全部移除。

为了提高找到落点区间的效率,这里可以使用二分法查找,我使用了之后发现运行耗时反而长了。不得不吐槽,测试用例不够强很吃亏。

需要注意的点:

  • 左端点若落在区间内,需要多移除一个区间。
  • 左端若不落在区间内,需要将移除起点后移一位。

解法

/**
 * @desc 二分法找到值落在的区间或落在的区间后
 * @returns {index, in} index为最接近的区间下标,向左靠齐,in标记在区间内还是外
 */
const findPosition = (intervals, val) => {
  let left = 0;
  let right = intervals.length;
  let middle = ~~((left + right) / 2);

  while (!(middle === left || middle === right)) {
    if (intervals[middle][0] <= val) {
      left = middle;
    } else {
      right = middle;
    }

    middle = ~~((left + right) / 2);
  }

  if (middle < intervals.length && val < intervals[middle][0]) {
    middle -= 1;
  }

  return { index: middle, in: Boolean(intervals[middle] && val <= intervals[middle][1]) };
};

/**
 * @param {number[][]} intervals
 * @param {number[]} newInterval
 * @return {number[][]}
 */
const insert = (intervals, newInterval) => {
  const left = findPosition(intervals, newInterval[0]);
  const right = findPosition(intervals, newInterval[1]);

  // 新区间落下后,影响到的原先区间数目,都要去除
  const removeCount = right.index - left.index + Number(left.in);
  // 去除的区间们的起点
  const removeStart = left.index + Number(!left.in);

  intervals.splice(removeStart, removeCount, [
    left.in ? intervals[left.index][0] : newInterval[0],
    right.in ? intervals[right.index][1] : newInterval[1],
  ]);

  return intervals;
};
Last Updated: 7/2/26, 2:05 AM
Contributors: henri.zhang
Prev
51. N皇后
Next
145. 二叉树的后序遍历