終わりの 順の 貪欲で 重なりを消す
1 台の
海外で定番の問題リスト 4 本には入っていません
問題
1 台の[始まり, 終わり] のjobs で
- 片方の
終わりと、 もう 片方の 始まりが 同じ (ちょうど接している ) 2 つは、 重ならないと見ます jobsは並べ替えられていません - どの
組も、 始まりは 終わりより 小さいです jobsの長さは 1 以上 100000 以下、 値は どれも -50000 以上 50000 以下です
入力と出力の例
例 1
[2, 3] と [4, 7] を[1, 5] と [6, 8] を
例 2
どの 2 つも
例 3
長い [0, 10] 1 つを
面接での聞かれ方
面接では、
- 「重なっている
会議が あります。 いく つ取り消せば重ならなくなりますか。 最少で 答えてください」 - 「接している
会議は 重なりますか」と 聞き返すと、 「重ならないとします」と 返ってくるのが ふつうです - 書き終えた
あとに 「なぜ 終わりの 順で 選ぶと 最少に なるのですか」と、 理由を 聞かれる こともあります
「外す最少」は
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
素直に
段 2
外す数を[0, 10] のように、
段 3
仕事を>= です。
解答
Python
Python
def remove_overlaps(jobs):
items = sorted(
jobs,
key=lambda iv: iv[1],
)
removed = 0
end = items[0][1]
for s, e in items[1:]:
if s >= end:
end = e
else:
removed += 1
return removedJavaScript
JavaScript
function removeOverlaps(jobs) {
const items = [...jobs];
items.sort(
(p, q) => p[1] - q[1],
);
let removed = 0;
let end = items[0][1];
const rest = items.slice(1);
for (const [s, e] of rest) {
if (s >= end) {
end = e;
} else {
removed++;
}
}
return removed;
}Go
Go
import "slices"
func removeOverlaps(
jobs [][]int,
) int {
items := slices.Clone(jobs)
slices.SortFunc(items, func(
p, q []int,
) int {
return p[1] - q[1]
})
removed := 0
end := items[0][1]
for _, iv := range items[1:] {
if iv[0] >= end {
end = iv[1]
} else {
removed++
}
}
return removed
}どのjobs を
計算量
- 時間は O(n log n) です。
並べ替えが O(n log n)、 その 後の なめる 処理は O(n) なので、 並べ替えが 全体を決めます - 使う
記憶は O(n) です。 並べ替えた 写しが n 個の 組を持ちます - 終わりが
同じ 仕事が 並んだ ときの 順は、 答えに 関わりません。 どちらを 先に 残しても、 次に 比べる 終わりは 同じだからです
よく ある間違い
- 始まりの
順に 並べて、 最初の 物を残す。 例 3 を 始まりの 順に 見ると、 最初の [0, 10]を残してしまい、 残り 3 つを 全部外して 答えが 3 に なります。 残す物は 終わりの 早い順に選びます - 接している
物を 重なりと数える。 比べる 式を s > endと書くと、 例 2 の [0, 3]と[3, 5]が重なると 見られ、 答えが 0 に なりません - 外した
仕事で 終わりを 更新する。 外すと 決めた 仕事の 終わりで endを書き換えると、 すでに 残した 仕事との 重なりを 見落とします。 endを変えるのは 残した ときだけです - 重なる
組の 数を数える。 重なっている 2 つの 組の 数を 返すと、 例 3 では [0, 10]が 3 つと重なるので 3 に なります。 1 つ外せば 3 組の 重なりが 同時に 消える ことがあります
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「外す
最少は、 残せる 最多と 同じ 問題です。 残す仕事を 選ぶときは、 終わりが 最も 早い物を 選べば 後ろに 使える 時間が 最も 多く 残るので、 終わりの 順に 並べて 前から 貪欲に 選びます。 次の 始まりが 最後に 残した 終わり以上 なら 残し、 そうでなければ 外して 数えます。 接している 物は 重ならないので >=で比べます。 時間は 並べ替えの O(n log n)、 記憶は 写しの O(n) です。」
書き終えたら、
「例 1 を
終わりの 順に 並べると [2, 3]、[1, 5]、[4, 7]、[6, 8]です。[2, 3]を残し、 終わりは 3 です。 [1, 5]は 1 が 3 より小さいので 外し、 1 本です。 [4, 7]は 4 が 3 以上なので 残し、 終わりは 7 です。 [6, 8]は 6 が 7 より小さいので 外し、 2 本です。 答えは 2 です。」