3 つの 組に 分けて 新しい 区間を差し込む
始まりの
海外で定番の問題リスト 4 本には入っていません
問題
ある[始まり, 終わり] のbooked でextra ([始まり, 終わり] の
bookedは始まりの 小さい 順に 並んでいて、 どの 2 つも 重ならず、 接してもいません bookedは空の こともあります - どの
組も、 始まりは 終わり以下です bookedの長さは 0 以上 10000 以下、 値は どれも 0 以上 100000 以下です - 渡された
bookedの中身は 書き換えないでください
入力と出力の例
例 1
[6, 10] は [5, 7] と [9, 12] の[5, 12] に
例 2
どれとも
例 3
[4, 8] は、[2, 4] とも[8, 9] とも
面接での聞かれ方
面接では、
- 「並んだ
予約の 一覧に、 新しい 予約を 1 つ足してください。 重なったら まとめてください」 - 「区間を
まとめる 問題と 同じように、 足してから 並べ替えれば いいですか」と 聞くと、 「並んでいる ことを 使ってください」と 返ってくるのが ふつうです - 「接している
予約は まとめますか」と、 端の 扱いを 聞かれる こともあります
入力が
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
素直にextra を booked のbooked が
段 2
booked をextra のextra とextra の
段 3
1 つ目のextra のextra のextra の< と <= の
解答
Python
Python
def insert_interval(booked, extra):
out = []
s, e = extra
i, n = 0, len(booked)
while i < n and booked[i][1] < s:
out.append(list(booked[i]))
i += 1
while i < n and booked[i][0] <= e:
s = min(s, booked[i][0])
e = max(e, booked[i][1])
i += 1
out.append([s, e])
while i < n:
out.append(list(booked[i]))
i += 1
return outJavaScript
JavaScript
function insertInterval(
booked, extra
) {
const out = [];
let [s, e] = extra;
const n = booked.length;
let i = 0;
while (
i < n && booked[i][1] < s
) {
out.push([...booked[i]]);
i++;
}
while (
i < n && booked[i][0] <= e
) {
s = Math.min(s, booked[i][0]);
e = Math.max(e, booked[i][1]);
i++;
}
out.push([s, e]);
while (i < n) {
out.push([...booked[i]]);
i++;
}
return out;
}Go
Go
func insertInterval(
booked [][]int, extra []int,
) [][]int {
out := [][]int{}
s, e := extra[0], extra[1]
i, n := 0, len(booked)
for i < n && booked[i][1] < s {
b := booked[i]
out = append(out,
[]int{b[0], b[1]})
i++
}
for i < n && booked[i][0] <= e {
s = min(s, booked[i][0])
e = max(e, booked[i][1])
i++
}
out = append(out, []int{s, e})
for ; i < n; i++ {
b := booked[i]
out = append(out,
[]int{b[0], b[1]})
}
return out
}どのbooked まで
計算量
- 時間は O(n) です。
bookedを前から 1 回なめるだけで、 どの 区間も 1 回しか見ません - 使う
記憶は O(n) です。 答えの 並びが 最悪 n + 1 本の 区間を持ちます - 足してから
並べ替える 書き方は O(n log n) かかるので、 並んでいる ことを 使う 分だけ 速くなります
よく ある間違い
- 接している
区間を落とす。 1 つ目の 組の 条件を booked[i][1] <= sと書くと、 例 3 の [2, 4]が「手前」に 入り、 [4, 8]とまとまりません。 手前に 入るのは 終わりが extraの始まりより 小さい 物だけです - 始まりを
広げ忘れる。 終わりだけを 大きい方に 取ると、 例 1 で 答えが [6, 12]になり、 [5, 7]の 5 が消えます。 重なった 区間の 始まりが extraより前の こともあります - 広げた 1 本を
足し忘れる。 2 つ目の 組が 空の とき (例 2) も、 extra自体は必ず 答えに 入ります。 2 つ目の ループの 後で、 条件なしに足します bookedが空の ときに 先頭を読む。 booked[0]を最初に 読む 書き方だと、 空の 並びで 止まります。 この 解き方は、 どの ループも i < nで守っているので 空でも動きます
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「足してから
並べ替えれば 区間を まとめる 問題と 同じに なりますが、 それだと O(n log n) です。 bookedは並んでいて 重ならないので、 extraより手前の 物、 重なる物、 後ろの 物の 3 つに 分かれて、 この 順に ひと 続きで 出てきます。 手前は そのまま 写し、 重なる物は extraを広げながら 飲み込み、 広げた 1 本を 足してから 後ろを 写します。 時間も 記憶も O(n) です。」
書き終えたら、
「例 1 で
たどります。 [1, 3]は 3 が 6 より小さいので 手前として 写します。 [5, 7]は 7 が 6 以上なので 手前ではなく、 5 が 10 以下なので 重なります。 始まりは 5、 終わりは 10 のままです。 [9, 12]も 9 が 10 以下なので重なり、 終わりが 12 に 伸びます。 [15, 18]は 15 が 12 より大きいので 止まり、 [5, 12]を足してから [15, 18]を写します。 答えは [[1, 3], [5, 12], [15, 18]]です。」