Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで各セルに最も近い0までのマンハッタン距離を格納した行列を生成するプログラム

問題の概要

0と1だけで構成される2値行列を考えます。この行列と同じサイズの新しい行列を作成してください。ただし、新しい行列の各セルには、元の行列においてその位置から最も近い0までのマンハッタン距離を格納します。なお、元の行列には少なくとも1つの0が存在すると仮定できます。

たとえば、入力が次のような行列だった場合を考えてみましょう。

101
101
110

このとき、出力は次のようになります。

101
101
210

これは、左下のセルだけが最も近い0までの距離が2になるためです。

解決のための手順

この問題は、動的計画法(DP)の考え方を応用し、行列を2回走査するだけで効率的に解くことができます。具体的な手順は以下の通りです。

  • m := 行列の行数、n := 行列の列数 とします。
  • y を 0 から m-1 まで繰り返します。
    • x を 0 から n-1 まで繰り返します。
      • matrix[y, x] が 0 以外の場合、matrix[y, x] := 無限大 と初期化します。
  • y を 0 から m-1 まで繰り返します(左上からの順方向パス)。
    • x を 0 から n-1 まで繰り返します。
      • y が 0 以外なら、matrix[y, x] = min(matrix[y, x], matrix[y - 1, x] + 1) と更新します。
      • x が 0 以外なら、matrix[y, x] = min(matrix[y, x], matrix[y, x - 1] + 1) と更新します。
  • y を m - 1 から 0 まで減らしながら繰り返します(右下からの逆方向パス)。
    • x を n - 1 から 0 まで減らしながら繰り返します。
      • y + 1 < m の場合、matrix[y, x] = min(matrix[y, x], matrix[y + 1, x] + 1) と更新します。
      • x + 1 < n の場合、matrix[y, x] = min(matrix[y, x], matrix[y, x + 1] + 1) と更新します。
  • matrix を返します。

アルゴリズムのポイント

まず、0以外のセルをすべて無限大で初期化します。その後、左上から右下へ向かう順方向のパスで「上」と「左」の隣接セルからの距離を伝播させ、続いて右下から左上へ向かう逆方向のパスで「下」と「右」の隣接セルからの距離を伝播させます。この2回の走査により、すべてのセルについて上下左右4方向からの最小距離が正しく求まり、計算量は O(m×n) に抑えられます。

それでは、理解を深めるために実際のPython実装を見てみましょう。

サンプルコード(Python)

import math

class Solution:
   def solve(self, matrix):
      m, n = len(matrix), len(matrix[0])
      for y in range(m):
         for x in range(n):
            if matrix[y][x]:
               matrix[y][x] = math.inf
      for y in range(m):
         for x in range(n):
            if y:
               matrix[y][x] = min(matrix[y][x], matrix[y - 1][x] + 1)
            if x:
               matrix[y][x] = min(matrix[y][x], matrix[y][x - 1] + 1)
      for y in range(m - 1, -1, -1):
         for x in range(n - 1, -1, -1):
            if y + 1 < m:
               matrix[y][x] = min(matrix[y][x], matrix[y + 1][x] + 1)
            if x + 1 < n:
               matrix[y][x] = min(matrix[y][x], matrix[y][x + 1] + 1)
      return matrix

ob = Solution()
matrix = [ [1, 0, 1], [1, 0, 1], [1, 1, 0] ]
print(ob.solve(matrix))

入力

[[1, 0, 1],
[1, 0, 1],
[1, 1, 0]]

出力

[[1, 0, 1], [1, 0, 1], [2, 1, 0]]
  1. Pythonでライフゲームを実装!セルマトリクスの次の状態を求めるプログラム

    問題の概要 2次元のバイナリ行列を考えます。「1」は生存しているセル(生きた細胞)、「0」は死んでいるセルを表します。あるセルの「近傍」とは、そのセルの上下左右および斜め方向に隣接する最大8個のセルのことです。 この記事では、以下のルールに従って行列全体の「次の状態」を求めるプログラムをPythonで実装します。このルールは、数学者ジョン・コンウェイが考案した有名な「ライフゲーム(Conways Game of Life)」と同じものです。 セルの状態遷移ルール 生存しているセルは、隣接する生存セルが2つまたは3つの場合に限り、次の世代でも生存します。 死んでいるセルは、隣接する生存セルが

  2. Pythonで文字列からすべての有効なIPアドレスの組み合わせを生成する方法

    数字のみで構成された文字列が与えられたとき、そこから生成できるすべての有効なIPアドレスの組み合わせを求めるのが本記事の目的です。 基本的な考え方は、まず文字列の長さを確認し、その後に「.(ドット)」を挿入する位置を3か所選んで分割します。ドットの挿入位置の組み合わせをすべて試すことで、有効なIPアドレスを網羅的に抽出できます。 実行例 Input : 255011123222 → 有効なIPアドレスとして成立しない場合もある Input : 255011345890 → 有効なIPアドレス: 255.011.123.222 アルゴリズム Step 1: まず文字列の長さを確認する。 S