Given a 2D grid of characters and a word/ multiple words, the task is to check if that word/words exist in the grid or not. A word can be matched in 4 directions at any point.
The 4 directions are Horizontally Left and Right, Vertically Up and Down.
Examples:
Input: grid[][] = {"axmy", "bgdf", "xeet", "raks"}; Output: Yes a x m y b g d f x e e t r a k s Input: grid[][] = {"axmy", "brdf", "xeet", "rass"}; Output : No
Source: Microsoft Interview
Approach when a single word is to be checked : The idea used here is described in the steps below:
- Check every cell, if the cell has the first character, then recur one by one and try all 4 directions from that cell for a match.
- Mark the position in the grid as visited and recur in the 4 possible directions.
- After recurring, again mark the position as unvisited.
- Once all the letters in the word are matched, return true.
Below is the implementation of the above approach:
C++
// C++ program to check if the word // exists in the grid or not #include <bits/stdc++.h> using namespace std; #define r 4 #define c 5 // Function to check if a word exists in a grid // starting from the first match in the grid // level: index till which pattern is matched // x, y: current position in 2D array bool findmatch( char mat[r], string pat, int x, int y, int nrow, int ncol, int level) { int l = pat.length(); // Pattern matched if (level == l) return true ; // Out of Boundary if (x < 0 || y < 0 || x >= nrow || y >= ncol) return false ; // If grid matches with a letter while // recursion if (mat[x][y] == pat[level]) { // Marking this cell as visited char temp = mat[x][y]; mat[x][y] = '#' ; // finding subpattern in 4 directions bool res = findmatch(mat, pat, x - 1, y, nrow, ncol, level + 1) | findmatch(mat, pat, x + 1, y, nrow, ncol, level + 1) | findmatch(mat, pat, x, y - 1, nrow, ncol, level + 1) | findmatch(mat, pat, x, y + 1, nrow, ncol, level + 1); // marking this cell // as unvisited again mat[x][y] = temp; return res; } else // Not matching then false return false ; } // Function to check if the word exists in the grid or not bool checkMatch( char mat[r], string pat, int nrow, int ncol) { int l = pat.length(); // if total characters in matrix is // less than pattern length if (l > nrow * ncol) return false ; // Traverse in the grid for ( int i = 0; i < nrow; i++) { for ( int j = 0; j < ncol; j++) { // If first letter matches, then recur and check if (mat[i][j] == pat[0]) if (findmatch(mat, pat, i, j, nrow, ncol, 0)) return true ; } } return false ; } // Driver Code int main() { char grid[r] = { "axmy" , "bgdf" , "xeet" , "raks" }; // Function to check if word exists or not if (checkMatch(grid, "neveropen" , r, c)) cout << "Yes" ; else cout << "No" ; return 0; } |
Java
// Java program to check if the word // exists in the grid or not class GFG { static final int r = 4 ; static final int c = 4 ; // Function to check if a word exists in a grid // starting from the first match in the grid // level: index till which pattern is matched // x, y: current position in 2D array static boolean findmatch( char mat[][], String pat, int x, int y, int nrow, int ncol, int level) { int l = pat.length(); // Pattern matched if (level == l) return true ; // Out of Boundary if (x < 0 || y < 0 || x >= nrow || y >= ncol) return false ; // If grid matches with a letter while // recursion if (mat[x][y] == pat.charAt(level)) { // Marking this cell as visited char temp = mat[x][y]; mat[x][y] = '#' ; // finding subpattern in 4 directions boolean res = findmatch(mat, pat, x - 1 , y, nrow, ncol, level + 1 ) | findmatch(mat, pat, x + 1 , y, nrow, ncol, level + 1 ) | findmatch(mat, pat, x, y - 1 , nrow, ncol, level + 1 ) | findmatch(mat, pat, x, y + 1 , nrow, ncol, level + 1 ); // marking this cell // as unvisited again mat[x][y] = temp; return res; } else // Not matching then false return false ; } // Function to check if the word exists in the grid or not static boolean checkMatch( char mat[][], String pat, int nrow, int ncol) { int l = pat.length(); // if total characters in matrix is // less than pattern length if (l > nrow * ncol) return false ; // Traverse in the grid for ( int i = 0 ; i < nrow; i++) { for ( int j = 0 ; j < ncol; j++) { // If first letter matches, then recur and check if (mat[i][j] == pat.charAt( 0 )) if (findmatch(mat, pat, i, j, nrow, ncol, 0 )) return true ; } } return false ; } // Driver Code public static void main(String[] args) { char grid[][] = { "axmy" .toCharArray(), "bgdf" .toCharArray(), "xeet" .toCharArray(), "raks" .toCharArray() }; // Function to check if word exists or not if (checkMatch(grid, "neveropen" , r, c)) System.out.print( "Yes" ); else System.out.print( "No" ); } } // This code is contributed by 29AjayKumar |
Python3
# Python3 program to check if the word # exists in the grid or not r = 4 c = 4 # Function to check if a word exists # in a grid starting from the first # match in the grid level: index till # which pattern is matched x, y: current # position in 2D array def findmatch(mat, pat, x, y, nrow, ncol, level) : l = len (pat) # Pattern matched if (level = = l) : return True # Out of Boundary if (x < 0 or y < 0 or x > = nrow or y > = ncol) : return False # If grid matches with a letter # while recursion if (mat[x][y] = = pat[level]) : # Marking this cell as visited temp = mat[x][y] mat[x].replace(mat[x][y], "#" ) # finding subpattern in 4 directions res = (findmatch(mat, pat, x - 1 , y, nrow, ncol, level + 1 ) | findmatch(mat, pat, x + 1 , y, nrow, ncol, level + 1 ) | findmatch(mat, pat, x, y - 1 , nrow, ncol, level + 1 ) | findmatch(mat, pat, x, y + 1 , nrow, ncol, level + 1 )) # marking this cell as unvisited again mat[x].replace(mat[x][y], temp) return res else : # Not matching then false return False # Function to check if the word # exists in the grid or not def checkMatch(mat, pat, nrow, ncol) : l = len (pat) # if total characters in matrix is # less than pattern length if (l > nrow * ncol) : return False # Traverse in the grid for i in range (nrow) : for j in range (ncol) : # If first letter matches, then # recur and check if (mat[i][j] = = pat[ 0 ]) : if (findmatch(mat, pat, i, j, nrow, ncol, 0 )) : return True return False # Driver Code if __name__ = = "__main__" : grid = [ "axmy" , "bgdf" , "xeet" , "raks" ] # Function to check if word # exists or not if (checkMatch(grid, "neveropen" , r, c)) : print ( "Yes" ) else : print ( "No" ) # This code is contributed by Ryuga |
Javascript
<script> // JavaScript program to check if the word // exists in the grid or not let r = 4; let c = 4; // Function to check if a word exists in a grid // starting from the first match in the grid // level: index till which pattern is matched // x, y: current position in 2D array function findmatch(mat, pat, x, y, nrow, ncol, level) { let l = pat.length; // Pattern matched if (level == l) return true ; // Out of Boundary if (x < 0 || y < 0 || x >= nrow || y >= ncol) return false ; // If grid matches with a letter while // recursion if (mat[x][y] == pat[level]) { // Marking this cell as visited let temp = mat[x][y]; mat[x][y] = '#' ; // finding subpattern in 4 directions let res = findmatch(mat, pat, x - 1, y, nrow, ncol, level + 1) | findmatch(mat, pat, x + 1, y, nrow, ncol, level + 1) | findmatch(mat, pat, x, y - 1, nrow, ncol, level + 1) | findmatch(mat, pat, x, y + 1, nrow, ncol, level + 1); // marking this cell // as unvisited again mat[x][y] = temp; return res; } else // Not matching then false return false ; } // Function to check if the word exists in the grid or not function checkMatch(mat, pat, nrow, ncol) { let l = pat.length; // if total characters in matrix is // less than pattern length if (l > nrow * ncol) return false ; // Traverse in the grid for (let i = 0; i < nrow; i++) { for (let j = 0; j < ncol; j++) { // If first letter matches, then recur and check if (mat[i][j] == pat[0]) if (findmatch(mat, pat, i, j, nrow, ncol, 0)) return true ; } } return false ; } let grid = [ "axmy" .split( '' ), "bgdf" .split( '' ), "xeet" .split( '' ), "raks" .split( '' ) ]; // Function to check if word exists or not if (checkMatch(grid, "neveropen" , r, c)) document.write( "Yes" ); else document.write( "No" ); </script> |
C#
// C# program to check if the word // exists in the grid or not using System; class GFG { static readonly int r = 4; static readonly int c = 4; // Function to check if a word exists in a grid // starting from the first match in the grid // level: index till which pattern is matched // x, y: current position in 2D array static bool findmatch( char [,]mat, String pat, int x, int y, int nrow, int ncol, int level) { int l = pat.Length; // Pattern matched if (level == l) return true ; // Out of Boundary if (x < 0 || y < 0 || x >= nrow || y >= ncol) return false ; // If grid matches with a letter while // recursion if (mat[x, y] == pat[level]) { // Marking this cell as visited char temp = mat[x, y]; mat[x, y] = '#' ; // finding subpattern in 4 directions bool res = findmatch(mat, pat, x - 1, y, nrow, ncol, level + 1) | findmatch(mat, pat, x + 1, y, nrow, ncol, level + 1) | findmatch(mat, pat, x, y - 1, nrow, ncol, level + 1) | findmatch(mat, pat, x, y + 1, nrow, ncol, level + 1); // marking this cell // as unvisited again mat[x, y] = temp; return res; } else // Not matching then false return false ; } // Function to check if the word exists in the grid or not static bool checkMatch( char [,]mat, String pat, int nrow, int ncol) { int l = pat.Length; // if total characters in matrix is // less than pattern length if (l > nrow * ncol) return false ; // Traverse in the grid for ( int i = 0; i < nrow; i++) { for ( int j = 0; j < ncol; j++) { // If first letter matches, then recur and check if (mat[i, j] == pat[0]) if (findmatch(mat, pat, i, j, nrow, ncol, 0)) return true ; } } return false ; } // Driver Code public static void Main(String[] args) { char [,]grid = { { 'a' , 'x' , 'm' , 'y' }, { 'b' , 'g' , 'd' , 'f' }, { 'x' , 'e' , 'e' , 't' }, { 'r' , 'a' , 'k' , 's' } }; // Function to check if word exists or not if (checkMatch(grid, "neveropen" , r, c)) Console.Write( "Yes" ); else Console.Write( "No" ); } } // This code is contributed by 29AjayKumar |
Yes
Time Complexity: O(r*c), as we are using recursion to traverse the matrix. Where r and c are the rows and columns of the grid.
Auxiliary Space: O(r*c), as we are using extra space for the matrix. Where r and c are the rows and columns of the grid.
Approach when a group of words are to be checked : The idea used here is described in the steps below:
- iterate through group of words and check every cell, if the cell has the first character, then recur one by one and try all 4 directions from that cell for a match.
- Mark the position in the grid as visited and recur in the 4 possible directions.
- After recurring, again mark the position as unvisited.
- Once all the letters in the word are matched, return true, put it in answer list.
- return the answer list from a function and display
C++
#include <bits/stdc++.h> using namespace std; // making a solution class to solve the problem and to keep // the components and functions of solution together class Solution { public : // making the possible moves in movers array // if 4 directions are to be checked vector<vector< int > > mover = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } }; // if 8 directions are to be checked // vector<vector<int>>mover={{1,0},{0,1},{-1,0},{0,-1},{1,1},{-1,-1},{1,-1},{-1,1}}; // making the board global variable vector<vector< char > > board; // depth first search for the string, with the // coordinates and a visited array to take care that we // do not overlap the places visited already bool dfs( int x, int y, string& s, vector<vector< bool > > vis) { // if string length becomes 0 means string is found if (s.length() == 0) return true ; vis[x][y] = true ; // making a solution boolean to see if we can // perform depth search to find answer bool sol = false ; // making possible moves for ( int i = 0; i < mover.size(); i++) { int curr_x = mover[i][0] + x; int curr_y = mover[i][1] + y; // checking for out of bound areas if (curr_x >= 0 && curr_x < board.size()) { if (curr_y >= 0 && curr_y < board[0].size()) { // checking for similarity in the first // letter and the visited array if (board[curr_x][curr_y] == s[0] && vis[curr_x][curr_y] == false ) { string k = s.substr( 1); // removing the first letter // from the string sol |= dfs(curr_x, curr_y, k, vis); } } } } return sol; } // making a function findwords to find words along with // their location which inputs the board and list of // words vector<string> findWords(vector<vector< char > >& board, vector<string>& words) { this ->board = board; // making board a global variable vector<string> ans; vector<vector< bool > > vis( board.size(), vector< bool >(board[0].size(), false )); // visited array for ( auto & word : words) { for ( int i = 0; i < board.size(); i++) { for ( int j = 0; j < board[i].size(); j++) { if (board[i][j] == word[0]) { // if first letter of(i,j)== // string's first letter then we can // perform dfs to check the // possibility of string being present // from location (i,j) string s = word.substr(1); if (dfs(i, j, s, vis)) { ans.push_back(word); break ; } } } if (ans.size() && ans.back() == word) break ; } } return ans; } }; int main() { // making 1 instance of class solution as solver Solution solver; vector<vector< char > > board = { { 'o' , 'a' , 'a' , 'n' }, { 'e' , 't' , 'a' , 'e' }, { 'i' , 'h' , 'k' , 'r' }, { 'i' , 'f' , 'l' , 'v' } }; vector<string> words = { "oath" , "pea" , "eat" , "rain" }; // using the function findwords from our solution class // to find the answer vector<string> ans = solver.findWords(board, words); // printing the answer cout << "words present:\n" ; for ( auto & part : ans) cout << part << endl; return 0; } //contributed by Naman Anand |
Java
import java.util.*; class Solution { // Making the possible moves in movers array int [][] mover = {{ 1 , 0 }, { 0 , 1 }, {- 1 , 0 }, { 0 , - 1 }}; // Making the board global variable char [][] board; // Depth first search for the string, with the // coordinates and a visited array to take care that we // do not overlap the places visited already public boolean dfs( int x, int y, String s, boolean [][] vis) { // If string length becomes 0 means string is found if (s.length() == 0 ) { return true ; } vis[x][y] = true ; // Making a solution boolean to see if we can // perform depth search to find answer boolean sol = false ; // Making possible moves for ( int i = 0 ; i < mover.length; i++) { int curr_x = mover[i][ 0 ] + x; int curr_y = mover[i][ 1 ] + y; // Checking for out of bound areas if (curr_x >= 0 && curr_x < board.length) { if (curr_y >= 0 && curr_y < board[ 0 ].length) { // Checking for similarity in the first // letter and the visited array if (board[curr_x][curr_y] == s.charAt( 0 ) && !vis[curr_x][curr_y]) { // Removing the first letter from the string String k = s.substring( 1 ); sol |= dfs(curr_x, curr_y, k, vis); } } } } return sol; } // Making a function findWords to find words along with // their location which inputs the board and list of // words public List<String> findWords( char [][] board, String[] words) { this .board = board; List<String> ans = new ArrayList<>(); for (String word : words) { boolean [][] vis = new boolean [board.length][board[ 0 ].length]; for ( int i = 0 ; i < board.length; i++) { for ( int j = 0 ; j < board[i].length; j++) { if (board[i][j] == word.charAt( 0 )) { // If first letter of(i,j)== // string's first letter then we can // perform dfs to check the // possibility of string being present // from location (i,j) String s = word.substring( 1 ); if (dfs(i, j, s, vis)) { ans.add(word); break ; } } } if (!ans.isEmpty() && ans.get(ans.size() - 1 ).equals(word)) { break ; } } } return ans; } } class Main { public static void main(String[] args) { // making 1 instance of class solution as solver Solution solver = new Solution(); char [][] board = { { 'o' , 'a' , 'a' , 'n' }, { 'e' , 't' , 'a' , 'e' }, { 'i' , 'h' , 'k' , 'r' }, { 'i' , 'f' , 'l' , 'v' } }; String[] words = { "oath" , "pea" , "eat" , "rain" }; //Function call System.out.println( "Words present: " ); List<String> arr = solver.findWords(board, words); for ( int i = 0 ; i < arr.size(); i++) { System.out.println(arr.get(i)); } } } |
Python3
class Solution: # making the possible moves in movers array # if 4 directions are to be checked mover = [ [ 1 , 0 ], [ 0 , 1 ], [ - 1 , 0 ], [ 0 , - 1 ] ] # if 8 directions are to be checked # mover = [[1,0], [0,1], [-1,0], [0,-1], [1,1], [-1,-1], [1,-1], [-1,1]] # making the board global variable board = [] # depth first search for the string, with the # coordinates and a visited array to take care that we # do not overlap the places visited already def dfs( self , x, y, s, vis): # if string length becomes 0 means string is found if len (s) = = 0 : return True vis[x][y] = True # making a solution boolean to see if we can # perform depth search to find answer sol = False # making possible moves for i in range ( len ( self .mover)): curr_x = self .mover[i][ 0 ] + x curr_y = self .mover[i][ 1 ] + y # checking for out of bound areas if curr_x > = 0 and curr_x < len ( self .board): if curr_y > = 0 and curr_y < len ( self .board[ 0 ]): # checking for similarity in the first # letter and the visited array if self .board[curr_x][curr_y] = = s[ 0 ] and vis[curr_x][curr_y] = = False : # removing the first letter from the string k = s[ 1 :] sol | = self .dfs(curr_x, curr_y, k, vis) return sol # making a function findwords to find words along with # their location which inputs the board and list of # words def findWords( self , board, words): self .board = board ans = [] for word in words: vis = [[ False for _ in range ( len (board[ 0 ]))] for _ in range ( len (board))] for i in range ( len (board)): for j in range ( len (board[i])): if board[i][j] = = word[ 0 ]: # if first letter of(i,j)== # string's first letter then we can # perform dfs to check the # possibility of string being present # from location (i,j) s = word[ 1 :] if self .dfs(i, j, s, vis): ans.append(word) break if ans and ans[ - 1 ] = = word: break return ans # making 1 instance of class solution as solver solver = Solution() board = [ [ 'o' , 'a' , 'a' , 'n' ], [ 'e' , 't' , 'a' , 'e' ], [ 'i' , 'h' , 'k' , 'r' ], [ 'i' , 'f' , 'l' , 'v' ] ] words = [ "oath" , "pea" , "eat" , "rain" ] #Function call print ( "Words present: " ) arr = solver.findWords(board, words) for i in range ( len (arr)): print (arr[i]) # This code is contributed by lokeshpotta20. |
Javascript
class Solution { // making the possible moves in movers array // if 4 directions are to be checked mover = [ [1, 0], [0, 1], [-1, 0], [0, -1] ]; // if 8 directions are to be checked // mover = [[1,0], [0,1], [-1,0], [0,-1], [1,1], [-1,-1], [1,-1], [-1,1]]; // making the board global variable board = []; // depth first search for the string, with the // coordinates and a visited array to take care that we // do not overlap the places visited already dfs(x, y, s, vis) { // if string length becomes 0 means string is found if (s.length === 0) { return true ; } vis[x][y] = true ; // making a solution boolean to see if we can // perform depth search to find answer let sol = false ; // making possible moves for (let i = 0; i < this .mover.length; i++) { let curr_x = this .mover[i][0] + x; let curr_y = this .mover[i][1] + y; // checking for out of bound areas if (curr_x >= 0 && curr_x < this .board.length) { if (curr_y >= 0 && curr_y < this .board[0].length) { // checking for similarity in the first // letter and the visited array if ( this .board[curr_x][curr_y] == s[0] && vis[curr_x][curr_y] == false ) { // removing the first letter from the string let k = s.substring(1); sol |= this .dfs(curr_x, curr_y, k, vis); } } } } return sol; } // making a function findwords to find words along with // their location which inputs the board and list of // words findWords(board, words) { this .board = board; let ans = []; for (let word of words) { let vis = new Array(board.length).fill( false ).map(() => new Array(board[0].length).fill( false )); for (let i = 0; i < board.length; i++) { for (let j = 0; j < board[i].length; j++) { if (board[i][j] == word[0]) { // if first letter of(i,j)== // string's first letter then we can // perform dfs to check the // possibility of string being present // from location (i,j) let s = word.substring(1); if ( this .dfs(i, j, s, vis)) { ans.push(word); break ; } } } if (ans.length && ans[ans.length - 1] == word) { break ; } } } return ans; } } // making 1 instance of class solution as solver let solver = new Solution(); let board = [ ['o ',' a ',' a ',' n '], [' e ',' t ',' a ',' e '], [' i ',' h ',' k ',' r '], [' i ',' f ',' l ',' v'] ]; let words = [ "oath" , "pea" , "eat" , "rain" ]; // Call the findWords method to search for words const foundWords = solver.findWords(board, words); // Print the words that were found console.log( "Words present:" ); foundWords.forEach(word => console.log(word)); |
C#
// c# program for the above approach using System; using System.Collections.Generic; using System.Linq; class Solution { // Making the possible moves in moves array private static readonly int [][] Moves = { new [] {1, 0}, new [] {0, 1}, new [] {-1, 0}, new [] {0, -1} }; // Making the board global variable private char [][] _board; // Making a function findWords to find words along with // their location which inputs the board and list of // words public IList< string > FindWords( char [][] board, string [] words) { _board = board; var result = new List< string >(); foreach ( var word in words) { if (Exists(word)) { result.Add(word); } } return result; } private bool Exists( string word) { for ( var i = 0; i < _board.Length; i++) { for ( var j = 0; j < _board[0].Length; j++) { if (_board[i][j] == word[0] && Search(word, i, j, 0)) { return true ; } } } return false ; } private bool Search( string word, int i, int j, int k) { if (k == word.Length) { return true ; } if (i < 0 || j < 0 || i == _board.Length || j == _board[0].Length) { return false ; } if (_board[i][j] != word[k]) { return false ; } var temp = _board[i][j]; _board[i][j] = '#' ; foreach ( var move in Moves) { if (Search(word, i + move[0], j + move[1], k + 1)) { _board[i][j] = temp; return true ; } } _board[i][j] = temp; return false ; } } // Driver Code public class Program { public static void Main() { // making 1 instance of class solution as solver var solver = new Solution(); var board = new char [][] { new char [] { 'o' , 'a' , 'a' , 'n' }, new char [] { 'e' , 't' , 'a' , 'e' }, new char [] { 'i' , 'h' , 'k' , 'r' }, new char [] { 'i' , 'f' , 'l' , 'v' } }; var words = new string [] { "oath" , "pea" , "eat" , "rain" }; var ans = solver.FindWords(board, words); Console.WriteLine( "Words present:" ); foreach ( var word in ans) { Console.WriteLine(word); } } } // This code is contributed by Prince Kumar |
words present: oath eat
Time Complexity: O(r*c*len(words)*number of words), as we are using recursion to traverse the matrix. Where r and c are the rows and columns of the grid.
Auxiliary Space: O(r*c*number of words), as we are using extra space for the matrix. Where r and c are the rows and columns of the grid.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!