2 本の指で 2 人とも空いている日を求める

区間問題 160

2 人それぞれの、日の順に並んだ休みの範囲の一覧から、2 人とも休みの範囲を並べて返す。両方の並びに指を 1 本ずつ置き、先に終わる方の指を進めれば、1 回なめるだけで全部の重なりが拾えます。

海外で定番の問題リスト 4 本には入っていません

問題

2 人の休みの日の範囲が、[初日, 最終日] の組の並び a と b で渡されます。範囲は初日と最終日の両方を含みます。2 人とも休みの日の範囲を、初日の小さい順に並べて返す関数を書いてください。

  • a も b も、初日の小さい順に並んでいて、同じ並びの中のどの 2 つも重ならず、接してもいません
  • 片方の最終日と、もう片方の初日が同じなら、その 1 日は 2 人とも休みです。[t, t] の 1 日の範囲として返します
  • a と b は、どちらも空のことがあります。2 人とも休みの日が無ければ、空の並び [] を返します
  • どの組も、初日は最終日以下です
  • a と b の長さはどちらも 0 以上 1000 以下、値はどれも 0 以上 1000000000 以下です

入力と出力の例

例 1

b の [3, 9] は a の 2 つの範囲にまたがるので、重なりが 2 つできます。

a = [[1, 4], [8, 12], [15, 20]] b = [[3, 9], [11, 16]]
[[3, 4], [8, 9], [11, 12], [15, 16]]

例 2

a の最終日と b の初日が同じ 6 日なので、その 1 日だけが重なります。

a = [[2, 6]] b = [[6, 10]]
[[6, 6]]

例 3

b の範囲は、a の 2 つの範囲のちょうど間にあり、どちらとも重なりません。

a = [[1, 3], [7, 9]] b = [[4, 6]]
[]

面接での聞かれ方

面接では、予定を合わせる話として出されることが多いです。

  • 「2 人の空いている時間の一覧があります。2 人とも空いている時間を全部出してください」
  • 「一覧は並んでいますか」と聞くと、「並んでいて、同じ人の中では重なりません」と返ってくるのがふつうです
  • 書き終えたあとに「3 人以上ならどうしますか」と、続きを聞かれることもあります

両端を含むかどうかで、例 2 の 1 日の扱いが変わります。書く前に確かめておきます。

ヒント

まだ開いていません

付箋は 3 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3答えに近い

アルゴリズムのチートシートの「配列と文字列」に、この型の要点を表とコードでまとめています。

配列と文字列の問題は、全部の組を調べると手間が大きくなる所を、窓や左右の添字で減らす形が多いです。

main.py
def interval_intersections(a: list[list[int]], b: list[list[int]]) -> list[list[int]]:
    """
    Goal: 何を返すか

    idea1: まず思いつく案
    -> runtime: O(?)  space: O(?)

    idea2: もっと速い案
    -> runtime: O(?)  space: O(?)

    edge case: 空、1 つだけ、など
    """
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(interval_intersections([[1, 4], [8, 12], [15, 20]], [[3, 9], [11, 16]]))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します