Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
Example:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.
Solution
This problem does not give start position, or direction restriction, so 1. Scan board, find starting position with matching word first letter 2. From starting position, DFS (4 (up, down, left, right 4 directions) match word's rest letters 3. For each visited letter, mark it as visited, here use board[i][j] = '*' to represent visited. 4. If one direction cannot continue, backtracking, mark start position unvisited, mark board[i][j] = word[start] 5. If found any matching, terminate 6. Otherwise, no matching found, return false.
For example:
board, word:SEE as below pic:
1. Scan board, found board[1,0] = word[0],match word first letter。
2. DFS(up, down, left, right 4 directions)
as below pic:
Staring position(1,0), check whether adjacent cells match word next letter E.
1. mark current position(1,0)as visited,board[1][0] = '*'
2. Up(0,0)letter='A' not match,
3. Down(2,0)letter='A',not match,
4. Left(-1,0)out of board boundry,not match,
5. right(1,1)letter='F',not match
as below pic:
Didn't find matching from starting position, so
1. backtracking,mart start position(1,0)as unvisited, board[1][0] = 'S'.
2. scan board, find next start position(1,3)which match word first letter
as below pic:
New starting position(1,3),check whether adjacent cells match word next letter E.
1. mark current position(1, 3)as already visited,board[1][3] = '*'
2. Up(0,3)letter='E', match, continue DFS search,refer position(0,3)DFS search steps.
3. Down(2,3)letter='E',match, since #2 DFS didn't find word matching, continue DFS search, rfer to position (2, 3) DFS search steps.
4. Left(1,2)letter='C',not match,
5. Right(1,4)out of board boundry,not match
as below pic:
Start position(0,3), DFS,check whether adjacent cells match word next letter E
1. marck current position(0,3)already visited,board[0][3] = '*'
2. Up (-1,3)out of board boundry,not match
3. Down(1,3)already visited,
4. Left(0,2)letter='C',not match
5. Right(1,4)out of board boundry,not match
as below pic:
Start from position(0,3)not matching word,
1. Backtracking,mark(0,3)as unvisited。board[0][3] = 'E'.
2. Backtracking to next position(2,3),DFS,check whether adjacent cells match word next letter 'E'
3. Up (1,3)visited, continue
4. Down(3,3)out of board boundry,not match
5. Left(2,2)letter='E', match
6. Right(2,4)out of board boundry,not match
as below pic:
Complexity Analysis
Time Complexity:O(m*n) - m is number of board rows, n is number of board columns
Space Complexity:O(1) - no extra space
Note:if use Set or boolean[][] mark position visited,need extra space O(m*n).
Key Points
Scan board, find start position which match word first letter, DFS
Remember visited letter
Backtracking if not found matching
Code (Java/Javascript/Python3)
Java Code
publicclassLC79WordSearch {publicbooleanexist(char[][] board,String word) {if (board ==null||board.length==0|| board[0].length==0|| word ==null||word.length() ==0) returntrue;int rows =board.length;int cols = board[0].length;for (int r =0; r < rows; r++) {for (int c =0; c < cols; c++) {// scan board, start with word first character if (board[r][c] ==word.charAt(0)) {if (helper(board, word, r, c,0)) {returntrue; } } } }returnfalse; }privatebooleanhelper(char[][] board,String word,int r,int c,int start) {// already match word all characters, return trueif (start ==word.length()) returntrue;if (!isValid(board, r, c)|| board[r][c] !=word.charAt(start)) returnfalse;// mark visited board[r][c] ='*';boolean res =helper(board, word, r +1, c, start +1)||helper(board, word, r, c +1, start +1)||helper(board, word, r -1, c, start +1)||helper(board, word, r, c -1, start +1);// backtracking to start position board[r][c] =word.charAt(start);return res; }privatebooleanisValid(char[][] board,int r,int c) {return r >=0&& r <board.length&& c >=0&& c < board[0].length; }}
Python3 Code
classSolution:defexist(self,board: List[List[str]],word:str) ->bool: m =len(board) n =len(board[0])defdfs(board,r,c,word,index):if index ==len(word):returnTrueif r <0or r >= m or c <0or c >= n or board[r][c] != word[index]:returnFalse board[r][c] ='*' res = dfs(board, r - 1, c, word, index + 1) or dfs(board, r + 1, c, word, index + 1) or dfs(board, r, c - 1, word, index + 1) or dfs(board, r, c + 1, word, index + 1)
board[r][c] = word[index]return resfor r inrange(m):for c inrange(n):if board[r][c] == word[0]:ifdfs(board, r, c, word, 0):returnTrue