Word Search
Problem
Given an m x n
grid of characters board
and a string word
, return true
if word
exists in the grid.
The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.
Example 1:
Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
Output: true
Example 2:
Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
Output: true
Example 3:
Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
Output: false
Constraints:
m == board.length
n = board[i].length
1 <= m, n <= 6
1 <= word.length <= 15
board
andword
consists of only lowercase and uppercase English letters.
Solution
Recursive Approach (DFS)
The approach involves selecting an index (i, j) and checking if it’s possible to form a word starting with the letter at board[i][j]. We try all elements of the board as the starting letter to see which one forms the desired word.
Each time we check a letter, we verify if the current board[i][j] matches the corresponding letter in the given word. If it doesn’t, we immediately return false. The pointer that keeps track of the given word is index
, which we increment by 1 whenever we check the next letter on the board.
If the current board[i][j] matches, we proceed to check the next letter in all four directions. If any direction returns true, we immediately return true without further checks. If all four directions fail, we return false.
Additionally, while on the (i, j) element, we maintain a separate matrix to track whether it has been visited. If we encounter an already visited element, we stop and return false.
Additionally, if the position (i,j) on the board is out of the given size, we return false.
class Solution {
public boolean check(char[][] board, String word, int i, int j, String currentWord, boolean[][] visited, int index){
if(word.equals(currentWord)) return true;
if(i<0 || i>=board.length || j<0 || j>=board[0].length ||
visited[i][j] || word.charAt(index)!=board[i][j]) return false;
visited[i][j] = true;
if(check(board, word, i, j+1, currentWord+board[i][j],visited, index+1) ||
check(board, word, i+1, j, currentWord+board[i][j],visited, index+1) ||
check(board, word, i, j-1, currentWord+board[i][j],visited, index+1) ||
check(board, word, i-1, j, currentWord+board[i][j],visited, index+1)) return true;
visited[i][j] = false;
return false;
}
public boolean exist(char[][] board, String word) {
boolean visited[][] = new boolean[board.length][board[0].length];
for(int i = 0; i<board.length; i++){
for(int j=0; j<board[0].length; j++){
if(check(board, word, i, j, "",visited,0)) return true;
}
}
return false;
}
}
Time and Space Complexity
L - Length of the word
Time
O(nxm) x O(3^L)
We iterate over each element as the starting letter, resulting in O(nxm). From each element, there are 4 possible directions, but effectively 3 or fewer since the caller is on the neighbouring element or if the caller is on the first/last column or row. As we progress through the word index by index, the maximum number of elements we touch is (L) hence there will 3^L possibilities.
Space
O(nxm) + O(L)
We store the visited matrix, which O(nxm), and the maximum stack trace it can take up is O(L), corresponding to the length of the word.
Subscribe to my newsletter
Read articles from Chetan Datta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Chetan Datta
Chetan Datta
I'm someone deeply engrossed in the world of software developement, and I find joy in sharing my thoughts and insights on various topics. You can explore my exclusive content here, where I meticulously document all things tech-related that spark my curiosity. Stay connected for my latest discoveries and observations.