先頭の行と列を印の置き場にし、0 のある行と列を全部 0 にする

行列の中に 0 があれば、その行と列を全部 0 にします。どの行と列を消すかの印を、行列の先頭の行と先頭の列に書き込めば、追加の記憶を O(1) に抑えられる練習です。

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

問題

表計算の道具で、m 行 n 列の整数の行列 matrix を扱います。値が 0 のマスがあれば、そのマスのある行と列の値を全部 0 にしてください。0 にするかどうかは、書き換える前の matrix の 0 だけで決めます。書き換えてできた 0 から、さらに広げることはしません。

  • 新しい行列を作らず、matrix をその場で書き換えてください。書き換えた matrix を返す関数にします
  • 追加の記憶は O(1) を目指してください
  • m と n はどちらも 1 以上 200 以下、値はどれも -2147483648 以上 2147483647 以下です

入力と出力の例

例 1

0 は 1 行 2 列にあるので、1 行目と 2 列目が全部 0 になります (行と列は 0 から数えます)。

matrix = [[3, 8, 2], [6, 4, 0], [5, 7, 9]]
[[3, 8, 0], [0, 0, 0], [5, 7, 0]]

例 2

先頭の列に 0 があります。0 行目と 0 列目が 0 になります。

matrix = [[0, 2, 4, 6], [1, 3, 5, 7]]
[[0, 0, 0, 0], [0, 3, 5, 7]]

例 3

0 が 2 つあり、消える行と列が交わります。

matrix = [[1, 2, 3], [4, 0, 6], [7, 8, 9], [0, 11, 12]]
[[0, 0, 3], [0, 0, 0], [0, 0, 9], [0, 0, 0]]

面接での聞かれ方

面接では、記憶の使い方を詰めていく問題として出されます。

  • 「0 がある行と列を全部 0 にしてください。その場で書き換えてください」
  • 0 の行と列を集合に覚える書き方を見せると、「追加の記憶を O(1) にできますか?」と続きます
  • 「見つけたその場で 0 にしたらどうなりますか?」と、まずい書き方の理由を聞かれることもあります

印をどこに置くかを工夫できるか、そして印の置き場そのものを書き換える順を間違えないかが見られています。

ヒント

まだ開いていません

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

  1. ヒント 2

  2. ヒント 3

  3. ヒント 4答えに近い

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

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

main.py
def zero_matrix(matrix: list[list[int]]) -> list[list[int]]:
    """
    Goal: 何を返すか

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

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

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


# 「実行」を押すと、この行の結果が出ます
print(zero_matrix([[3, 8, 2], [6, 4, 0], [5, 7, 9]]))

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