Pythonで2次元グリッド内の単語検索を実装する方法【再帰・バックトラッキング】
2次元のボード(グリッド)と1つの単語が与えられたとき、その単語がグリッド内に存在するかどうかを判定する問題を考えてみましょう。単語は、順番に隣接するセルの文字をつなげて構成されます。ここでいう「隣接」とは、上下左右に位置するセルのことです。また、同じセル(同じ文字)を複数回使用することはできません。
例として、次のようなマトリックスがあるとします。
| A | B | C | E |
| S | F | C | S |
| A | D | E | F |
このとき、単語「ABCCED」が与えられれば答えは True、「SEE」も True になります。しかし「ABCB」の場合は、同じセルを再利用できないため False となります。
解法のアプローチ:再帰とバックトラッキング
この問題は再帰的な探索(バックトラッキング)を使うことで効率的に解けます。各セルから出発して上下左右へ文字をたどり、条件に合わなくなったら一歩戻って別の経路を試すイメージです。
手順の詳細
- 再帰メソッド
find()を定義します。引数はマトリックスmat、単語word、行row、列col、インデックスiです。最初はi = 0から始めます。 iが単語の長さと等しくなれば、すべての文字を照合できたということなのでTrueを返します。rowが行数以上または0未満、colが列数以上または0未満、もしくはword[i]がmat[row][col]と一致しない場合はFalseを返します。mat[row][col] := "*"として、現在のセルを一時的に「訪問済み」マークを付けます。これにより同じセルを二重に使うことを防ぎます。- 4方向(下・上・右・左)それぞれに対して
find()を再帰的に呼び出し、結果を OR で結合します。res := find(mat, word, row+1, col, i+1) or find(mat, word, row-1, col, i+1) or find(mat, word, row, col+1, i+1) or find(mat, word, row, col-1, i+1) mat[row][col] := word[i]としてセルの値を元に戻します(これがバックトラッキングの核心部分です)。resを返します。
メイン処理の流れ
n:= 行数、m:= 列数 とします。- すべてのセル
(i, j)についてループを行い、word[0]がmat[i][j]と一致するセルを見つけたら、そこを出発点としてfind()を呼び出します。 find()の結果がFalseでなければ、単語が見つかったのでTrueを返します。
実装例
それでは、実際のPythonコードを見てみましょう。
class Solution(object): def exist(self, board, word): n = len(board) m = len(board[0]) # すべてのセルを出発点候補として調べる for i in range(n): for j in range(m): if word[0] == board[i][j]: if self.find(board, word, i, j): return True return False def find(self, board, word, row, col, i=0): # 単語の最後まで照合できたら成功 if i == len(word): return True # 範囲外または文字が一致しない場合は失敗 if row >= len(board) or row < 0 or col >= len(board[0]) or col < 0 or word[i] != board[row][col]: return False # 訪問済みマークを付けて同じセルの再利用を防止 board[row][col] = '*' # 4方向へ再帰的に探索 res = self.find(board, word, row+1, col, i+1) or self.find(board, word, row-1, col, i+1) or self.find(board, word, row, col+1, i+1) or self.find(board, word, row, col-1, i+1) # セルの値を元に戻す(バックトラッキング) board[row][col] = word[i] return res ob1 = Solution() print(ob1.exist([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "SEE"))
入力
[["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]] "SEE"
出力
True
まとめ
この実装では、グリッド上の各セルを起点として深さ優先探索(DFS)を行い、訪問済みセルを一時的に書き換えることで同じ文字の再利用を防いでいます。探索後には必ず元の値に戻すことで、他の出発点からの探索にも影響を与えません。計算量は最悪ケースで O(m × n × 3^L)(L は単語の長さ)となり、バックトラッキングを用いた典型的なグリッド探索問題として、LeetCode の「Word Search」などでもおなじみのパターンです。
-
Pythonで学ぶ線形探索(リニアサーチ)の基本と実装方法
この記事では、最も基本的な検索アルゴリズムの一つである「線形探索(Linear Search)」の仕組みを理解し、Python 3.xでの実装方法をわかりやすく解説します。 線形探索のアルゴリズム 配列 arr[] の左端の要素から順に、目的の要素 x と各要素を一つずつ比較していきます x がいずれかの要素と一致した場合、そのインデックス(位置)を返します x が配列内のどの要素とも一致しなかった場合、-1 を返すか「要素が見つからない」ことを示します それでは、このアプローチの流れを視覚的に確認してみましょう。 実装例 def linearsearch(arr, x):
-
PythonでWordCloud(ワードクラウド)を作成する方法
このチュートリアルでは、テキストファイルとマスク画像を用意し、そこからワードクラウド(Word Cloud)を生成して png 形式の画像として保存するプログラムをPythonで作成します。 この処理を実装するには、以下のPythonライブラリが必要です。 ・matplotlib ・wordcloud ・numpy ・tkinter ・PIL ライブラリのセットアップ まず、必要なライブラリを次のコマンドでインストールします。 $ sudo pip3 install matplotlib $ sudo pip3 install wordcloud $ sudo apt-get install