始まりと 終わりを 分けて 要る 部屋の 数を数える
研修の
海外で定番の問題リスト 4 本には入っていません
問題
研修の[初日, 最終日] のplans で
- 片方の
最終日と、 もう 片方の 初日が 同じ 2 つの 研修は、 その 日に 重なるので 同じ 部屋に 入れられません plansは並べ替えられていません - どの
組も、 初日は 最終日以下です plansの長さは 1 以上 100000 以下、 値は どれも 1 以上 1000000 以下です
入力と出力の例
例 1
3 日目は [1, 5]、[2, 3]、[3, 7] の 3 つが
例 2
どの 2 つも
例 3
6 日目に 2 つの
面接での聞かれ方
面接では、
- 「会議の
時間帯の 一覧が あります。 会議室は いくつ あれば 足りますか」 - 「終わりと
始まりが 同じ 会議は、 同じ 部屋で 続けて できますか」と 聞くと、 場面に よって 答えが 変わります。 この 問題では 日の 単位なので、 同じ 日は 重なるとします - 書き終えた
あとに 「どの 研修を どの 部屋に 入れるかも返してください」と、 続きを 聞かれる こともあります
要る
ヒント
まだ開いていません
付箋は 3 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
素直に
段 2
開かれている
段 3
どの
解答
Python
Python
def min_groups(plans):
starts = sorted(
p[0] for p in plans
)
ends = sorted(
p[1] for p in plans
)
rooms = 0
j = 0
for s in starts:
if ends[j] < s:
j += 1
else:
rooms += 1
return roomsJavaScript
JavaScript
function minGroups(plans) {
const byNum = (p, q) => p - q;
const starts = plans
.map((p) => p[0])
.sort(byNum);
const ends = plans
.map((p) => p[1])
.sort(byNum);
let rooms = 0;
let j = 0;
for (const s of starts) {
if (ends[j] < s) {
j++;
} else {
rooms++;
}
}
return rooms;
}Go
Go
import "slices"
func minGroups(
plans [][]int,
) int {
n := len(plans)
starts := make([]int, n)
ends := make([]int, n)
for i, p := range plans {
starts[i] = p[0]
ends[i] = p[1]
}
slices.Sort(starts)
slices.Sort(ends)
rooms, j := 0, 0
for _, s := range starts {
if ends[j] < s {
j++
} else {
rooms++
}
}
return rooms
}JavaScript の sort は、[10, 9] が [10, 9] のまま(p, q) => p - q を
計算量
- 時間は O(n log n) です。
2 つの 並べ替えが O(n log n)、 その 後の なめる 処理は O(n) です - 使う
記憶は O(n) です。 初日と 最終日の 並びを 1 つずつ持ちます - 初日の
順に 並べ、 使っている 部屋の 最終日を 最小ヒープに 入れる 書き方でも 同じ 計算量です。 どの 部屋に 入れたかまで 返すときは、 ヒープの 書き方が 向いています
よく ある間違い
- 同じ
日を 重ならないと見る。 空いたと 見る 式を ends[j] <= sと書くと、 例 3 の [2, 6]と[6, 8]が同じ 部屋に 入り、 答えが 1 に なります。 この 問題では 同じ 日は 重なるので <です - 重なる
組の 数を数える。 重なる 2 つの 組を 数えると、 例 1 では [1, 5]と[2, 3]、[1, 5]と[3, 7]、[2, 3]と[3, 7]、[3, 7]と[6, 9]、[6, 9]と[9, 10]の 5 組になります。 要るのは 同じ 日に 開かれている 数の最大です - 初日の
順に 並べ、 直前の 研修とだけ比べる。 直前と 重なるかだけを 見ると、 例 1 の [3, 7]が[2, 3]と重なる ことは 分かっても、 [1, 5]もまだ 部屋を 使っている ことを 見落とします - 最終日の
並びの 指を 初日ごとに 必ず進める。 指を 進めるのは 部屋が 空いた ときだけです。 毎回進めると、 まだ 使われている 部屋を 空いたと数えます
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「要る
部屋の 数は、 同じ 日に 開かれている 研修の 数の 最大です。 どの 部屋が 空いたかは 要らず、 数だけ分かれば よいので、 初日と 最終日を 別々に 並べ替えます。 初日を 小さい 順に 見て、 まだ 使い回していない 最終日の うち最も 早い物が その 初日より 前なら 部屋を 使い回し、 そうでなければ 部屋を 足します。 同じ 日は 重なるので、 比べるのは <です。時間は O(n log n)、 記憶は O(n) です。」
書き終えたら、
「例 1 の
初日は 1、 2、 3、 6、 9、 最終日は 3、 5、 7、 9、 10 です。 初日 1 は、 最終日 3 が 1 より 前ではないので 部屋を 足して 1 つです。 初日 2 も 足して 2 つ、 初日 3 は 最終日 3 と 同じ 日なので 足して 3 つです。 初日 6 は 最終日 3 が 6 より 前なので 使い回して 指を 5 へ、 初日 9 も 5 が 9 より 前なので 使い回します。 答えは 3 です。」