Given a string array dictionary[] of size n containing distinct words and a character matrix board[][] of size r × c, find all words from the dictionary that can be formed in the board.
A word can be formed by starting from any cell and moving to any of its 8 adjacent cells (horizontally, vertically, or diagonally).
Each cell can be used at most once while forming a single word.
Return all dictionary words that can be formed in the board.
Note: The words in the output can be returned in any order.
Example:
Input: board[][] = [[C, A, P], [A, N, D], [T, I, E]], dictionary[] = ["CAT"] Output: ["CAT"] Explanation: "CAT" can be formed by traversing adjacent cells (8 directions) without reusing any cell.
Input: board[][] = [[G, I, Z], [U, E, K], [Q, S, E]], dictionary[] = ["GEEKS", "FOR", "QUIZ", "GO"] Output: ["GEEKS","QUIZ"] Explanation: "GEEKS" and "QUIZ" can be formed by traversing adjacent cells (8 directions) without reusing any cell.
[Naive Approach] DFS from Every Cell - O(r × c × 8^l + l) Time and O(r × c + l) Space
The idea is to treat every cell in the matrix as a potential starting point and generate all words that begin with the cell using depth - first search. For every generated word, check if it is present in the given set of words. If yes, then add it to the result and remove it from the given words to avoid duplicates. During DFS search, it is crucial to maintain a record of visited cells, ensuring that each cell is used only once in forming any given word.
C++
#include<bits/stdc++.h>usingnamespacestd;// DFS to explore all possible paths from (i, j)voiddfs(vector<vector<char>>&board,vector<vector<bool>>&visited,inti,intj,string&str,unordered_set<string>&wordSet,vector<string>&ans){intn=board.size();intm=board[0].size();// Step 1: Boundary check + visited checkif(i<0||i>=n||j<0||j>=m||visited[i][j])return;// Step 2: Mark current cell as visitedvisited[i][j]=true;// Step 3: Add current character to forming stringstr.push_back(board[i][j]);// Step 4: Check if current string exists in dictionary setif(wordSet.find(str)!=wordSet.end()){ans.push_back(str);// remove to avoid duplicateswordSet.erase(str);}// Step 5: Explore all 8 directions (including diagonals)for(intdx=-1;dx<=1;dx++){for(intdy=-1;dy<=1;dy++){// skip current cell itselfif(dx==0&&dy==0)continue;dfs(board,visited,i+dx,j+dy,str,wordSet,ans);}}// Step 6: Backtrackingstr.pop_back();// unmark current cell so it can be used in other pathsvisited[i][j]=false;}vector<string>wordBoggle(vector<vector<char>>&board,vector<string>&dictionary){intn=board.size();intm=board[0].size();vector<string>ans;// Step 1: Store dictionary in a hash set for fast lookupunordered_set<string>wordSet(dictionary.begin(),dictionary.end());// Step 2: Visited array to avoid reusing same cell in one pathvector<vector<bool>>visited(n,vector<bool>(m,false));stringstr="";// Step 3: Start DFS from every cell in the gridfor(inti=0;i<n;i++){for(intj=0;j<m;j++){dfs(board,visited,i,j,str,wordSet,ans);}}returnans;}intmain(){vector<string>dictionary={"GEEKS","FOR","QUIZ","GO"};vector<vector<char>>board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};vector<string>res=wordBoggle(board,dictionary);if(res.empty()){cout<<"[]";}else{sort(res.begin(),res.end());cout<<"[";for(inti=0;i<res.size();i++){cout<<"\""<<res[i]<<"\"";if(i+1!=res.size())cout<<",";}cout<<"]";}return0;}
Java
importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Collections;importjava.util.HashSet;classGFG{// DFS to explore all possible paths from (i, j)staticvoiddfs(char[][]board,boolean[][]visited,inti,intj,StringBuilderstr,HashSet<String>wordSet,ArrayList<String>ans){intn=board.length;intm=board[0].length;// Step 1: Boundary check + visited checkif(i<0||i>=n||j<0||j>=m||visited[i][j])return;// Step 2: Mark current cell as visitedvisited[i][j]=true;// Step 3: Add current character to forming stringstr.append(board[i][j]);// Step 4: Check if current string exists in// dictionary setif(wordSet.contains(str.toString())){ans.add(str.toString());wordSet.remove(str.toString());}// Step 5: Explore all 8 directionsfor(intdx=-1;dx<=1;dx++){for(intdy=-1;dy<=1;dy++){if(dx==0&&dy==0)continue;dfs(board,visited,i+dx,j+dy,str,wordSet,ans);}}// Step 6: Backtrackingstr.deleteCharAt(str.length()-1);visited[i][j]=false;}staticArrayList<String>wordBoggle(char[][]board,String[]dictionary){intn=board.length;intm=board[0].length;ArrayList<String>ans=newArrayList<>();HashSet<String>wordSet=newHashSet<>(Arrays.asList(dictionary));boolean[][]visited=newboolean[n][m];StringBuilderstr=newStringBuilder();for(inti=0;i<n;i++){for(intj=0;j<m;j++){dfs(board,visited,i,j,str,wordSet,ans);}}returnans;}publicstaticvoidmain(String[]args){String[]dictionary={"GEEKS","FOR","QUIZ","GO"};char[][]board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};ArrayList<String>res=wordBoggle(board,dictionary);Collections.sort(res);System.out.print(res);}}
Python
# DFS to explore all possible paths from (i, j)defdfs(board,visited,i,j,str,wordSet,ans):n=len(board)m=len(board[0])# Step 1: Boundary check + visited checkifi<0ori>=norj<0orj>=morvisited[i][j]:return# Step 2: Mark current cell as visitedvisited[i][j]=True# Step 3: Add current character to forming stringstr+=board[i][j]# Step 4: Check if current string exists in dictionary setifstrinwordSet:ans.append(str)wordSet.remove(str)# Step 5: Explore all 8 directionsfordxinrange(-1,2):fordyinrange(-1,2):ifdx==0anddy==0:continuedfs(board,visited,i+dx,j+dy,str,wordSet,ans)# Step 6: Backtrackingvisited[i][j]=FalsedefwordBoggle(board,dictionary):n=len(board)m=len(board[0])ans=[]wordSet=set(dictionary)visited=[[False]*mfor_inrange(n)]str=""foriinrange(n):forjinrange(m):dfs(board,visited,i,j,str,wordSet,ans)returnansif__name__=="__main__":dictionary=["GEEKS","FOR","QUIZ","GO"]board=[['G','I','Z'],['U','E','K'],['Q','S','E']]res=wordBoggle(board,dictionary)print(sorted(res))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// DFS to explore all possible paths from (i, j)voiddfs(char[,]board,bool[,]visited,inti,intj,stringstr,HashSet<string>wordSet,List<string>ans){intn=board.GetLength(0);intm=board.GetLength(1);// Step 1: Boundary check + visited checkif(i<0||i>=n||j<0||j>=m||visited[i,j])return;// Step 2: Mark current cell as visitedvisited[i,j]=true;// Step 3: Add current character to forming stringstr=str+board[i,j];// Step 4: Check if current string exists in// dictionary setif(wordSet.Contains(str)){ans.Add(str);// remove to avoid duplicateswordSet.Remove(str);}// Step 5: Explore all 8 directions (including// diagonals)for(intdx=-1;dx<=1;dx++){for(intdy=-1;dy<=1;dy++){if(dx==0&&dy==0)continue;dfs(board,visited,i+dx,j+dy,str,wordSet,ans);}}// Step 6: Backtrackingvisited[i,j]=false;}publicList<string>wordBoggle(char[,]board,string[]dictionary){intn=board.GetLength(0);intm=board.GetLength(1);List<string>ans=newList<string>();HashSet<string>wordSet=newHashSet<string>(dictionary);bool[,]visited=newbool[n,m];stringstr="";for(inti=0;i<n;i++){for(intj=0;j<m;j++){dfs(board,visited,i,j,str,wordSet,ans);}}returnans;}// Driver codestaticvoidMain(){string[]dictionary={"GEEKS","FOR","QUIZ","GO"};char[,]board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};GFGobj=newGFG();List<string>res=obj.wordBoggle(board,dictionary);res.Sort();Console.Write("[");for(inti=0;i<res.Count;i++){Console.Write("\""+res[i]+"\"");if(i!=res.Count-1)Console.Write(",");}Console.Write("]");}}
JavaScript
// DFS to explore all possible paths from (i, j)functiondfs(board,visited,i,j,str,wordSet,ans){letn=board.length;letm=board[0].length;// Step 1: Boundary check + visited checkif(i<0||i>=n||j<0||j>=m||visited[i][j])return;// Step 2: Mark current cell as visitedvisited[i][j]=true;// Step 3: Add current character to forming stringstr+=board[i][j];// Step 4: Check if current string exists in dictionary// setif(wordSet.has(str)){ans.push(str);wordSet.delete(str);}// Step 5: Explore all 8 directionsfor(letdx=-1;dx<=1;dx++){for(letdy=-1;dy<=1;dy++){if(dx===0&&dy===0)continue;dfs(board,visited,i+dx,j+dy,str,wordSet,ans);}}// Step 6: Backtrackingvisited[i][j]=false;}functionwordBoggle(board,dictionary){letn=board.length;letm=board[0].length;letans=[];letwordSet=newSet(dictionary);letvisited=Array.from({length:n},()=>Array(m).fill(false));letstr="";for(leti=0;i<n;i++){for(letj=0;j<n;j++){dfs(board,visited,i,j,str,wordSet,ans);}}returnans.sort();}// Driver codeconstdictionary=["GEEKS","FOR","QUIZ","GO"];constboard=[['G','I','Z'],['U','E','K'],['Q','S','E']];console.log(wordBoggle(board,dictionary));
Output
["GEEKS","QUIZ"]
[Better Approach] Word-by-Word DFS - O(n × r × c × 8^l) Time and O(r × c + l) Space
The idea is to check every word in the dictionary one by one and verify whether it can be formed from the given board using Depth First Search (DFS).
For each word, we start DFS from every cell in the board and try to match characters sequentially. During traversal, we mark cells as visited to avoid reusing them in the same path and unmark them while backtracking.
C++
#include<bits/stdc++.h>usingnamespacestd;// function to perform dfs on the gridbooldfs(vector<vector<char>>&board,stringword,inti,intj,intindex){intn=board.size();intm=board[0].size();// check if the current cell is out of boundsif(i<0||i>=n||j<0||j>=m)returnfalse;// check if the current cell matches the character in the wordif(board[i][j]!=word[index])returnfalse;// check if we have found the complete wordif(index==word.size()-1)returntrue;// mark the current cell as visitedchartemp=board[i][j];board[i][j]='#';// perform dfs on all 8 directionsfor(introw=-1;row<=1;row++){for(intcol=-1;col<=1;col++){// skip the current cellif(row==0&&col==0)continue;if(dfs(board,word,i+row,j+col,index+1)){board[i][j]=temp;returntrue;}}}// unmark the current cell as visitedboard[i][j]=temp;returnfalse;}// find all words in a given grid of charactersvector<string>wordBoggle(vector<vector<char>>&board,vector<string>&dictionary){intn=board.size();intm=board[0].size();vector<string>ans;unordered_set<string>result;// try each word from dictionaryfor(inti=0;i<dictionary.size();i++){stringword=dictionary[i];// try every starting cell in boardfor(intr=0;r<n;r++){for(intc=0;c<m;c++){if(dfs(board,word,r,c,0)){result.insert(word);}}}}// convert set to vectorfor(auto&word:result)ans.push_back(word);returnans;}intmain(){vector<string>dictionary={"GEEKS","FOR","QUIZ","GO"};vector<vector<char>>board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};vector<string>ans=wordBoggle(board,dictionary);sort(ans.begin(),ans.end());cout<<"[";for(inti=0;i<ans.size();i++){cout<<"\""<<ans[i]<<"\"";if(i!=ans.size()-1)cout<<",";}cout<<"]";return0;}
Java
importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Collections;importjava.util.HashSet;classGFG{// function to perform dfs on the gridstaticbooleandfs(char[][]board,Stringword,inti,intj,intindex){intn=board.length;intm=board[0].length;// check if the current cell is out of boundsif(i<0||i>=n||j<0||j>=m)returnfalse;// check if the current cell matches the character in the wordif(board[i][j]!=word.charAt(index))returnfalse;// check if we have found the complete wordif(index==word.length()-1)returntrue;// mark the current cell as visitedchartemp=board[i][j];board[i][j]='#';// perform dfs on all 8 directionsfor(introw=-1;row<=1;row++){for(intcol=-1;col<=1;col++){if(row==0&&col==0)continue;if(dfs(board,word,i+row,j+col,index+1)){board[i][j]=temp;returntrue;}}}// unmark the current cell as visitedboard[i][j]=temp;returnfalse;}// find all words in a given grid of charactersstaticArrayList<String>wordBoggle(char[][]board,String[]dictionary){intn=board.length;intm=board[0].length;ArrayList<String>ans=newArrayList<>();HashSet<String>result=newHashSet<>();// try each word from dictionaryfor(Stringword:dictionary){// try every starting cell in boardfor(intr=0;r<n;r++){for(intc=0;c<m;c++){if(dfs(board,word,r,c,0)){result.add(word);break;}}}}ans.addAll(result);returnans;}publicstaticvoidmain(String[]args){String[]dictionary={"GEEKS","FOR","QUIZ","GO"};char[][]board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};ArrayList<String>ans=wordBoggle(board,dictionary);Collections.sort(ans);System.out.print(ans);}}
Python
# function to perform dfs on the griddefdfs(board,word,i,j,index):n=len(board)m=len(board[0])# check if the current cell is out of boundsifi<0ori>=norj<0orj>=m:returnFalse# check if the current cell matches the character in the wordifboard[i][j]!=word[index]:returnFalse# check if we have found the complete wordifindex==len(word)-1:returnTrue# mark the current cell as visitedtemp=board[i][j]board[i][j]='#'# perform dfs on all 8 directionsforrowinrange(-1,2):forcolinrange(-1,2):ifrow==0andcol==0:continueifdfs(board,word,i+row,j+col,index+1):board[i][j]=tempreturnTrue# unmark the current cell as visitedboard[i][j]=tempreturnFalse# find all words in a given grid of charactersdefwordBoggle(board,dictionary):n=len(board)m=len(board[0])result=set()# try each word from dictionaryforwordindictionary:# try every starting cell in boardforrinrange(n):forcinrange(m):ifdfs(board,word,r,c,0):result.add(word)returnlist(result)if__name__=="__main__":dictionary=["GEEKS","FOR","QUIZ","GO"]board=[['G','I','Z'],['U','E','K'],['Q','S','E']]ans=wordBoggle(board,dictionary)print(sorted(ans))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// function to perform dfs on the gridstaticbooldfs(char[,]board,stringword,inti,intj,intindex){intn=board.GetLength(0);intm=board.GetLength(1);// check if the current cell is out of boundsif(i<0||i>=n||j<0||j>=m)returnfalse;// check if the current cell matches the character in the wordif(board[i,j]!=word[index])returnfalse;// check if we have found the complete wordif(index==word.Length-1)returntrue;// mark the current cell as visitedchartemp=board[i,j];board[i,j]='#';// perform dfs on all 8 directionsfor(introw=-1;row<=1;row++){for(intcol=-1;col<=1;col++){if(row==0&&col==0)continue;if(dfs(board,word,i+row,j+col,index+1)){board[i,j]=temp;// backtrackreturntrue;}}}// unmark the current cell as visitedboard[i,j]=temp;returnfalse;}// find all words in a given grid of characterspublicstaticList<string>wordBoggle(char[,]board,string[]dictionary){intn=board.GetLength(0);intm=board.GetLength(1);List<string>ans=newList<string>();HashSet<string>result=newHashSet<string>();// try each word from dictionaryforeach(stringwordindictionary){// try every starting cell in boardfor(intr=0;r<n;r++){for(intc=0;c<m;c++){if(dfs(board,word,r,c,0))result.Add(word);}}}returnnewList<string>(result);}staticvoidMain(){string[]dictionary={"GEEKS","FOR","QUIZ","GO"};char[,]board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};List<string>ans=wordBoggle(board,dictionary);ans.Sort();Console.Write("[");for(inti=0;i<ans.Count;i++){Console.Write("\""+ans[i]+"\"");if(i!=ans.Count-1)Console.Write(",");}Console.Write("]");}}
JavaScript
// function to perform dfs on the gridfunctiondfs(board,word,i,j,index){letn=board.length;letm=board[0].length;// check if the current cell is out of boundsif(i<0||i>=n||j<0||j>=m)returnfalse;// check if the current cell matches the character in the wordif(board[i][j]!=word[index])returnfalse;// check if we have found the complete wordif(index==word.length-1)returntrue;// mark the current cell as visitedlettemp=board[i][j];board[i][j]='#';// perform dfs on all 8 directionsfor(letrow=-1;row<=1;row++){for(letcol=-1;col<=1;col++){if(row==0&&col==0)continue;if(dfs(board,word,i+row,j+col,index+1)){board[i][j]=temp;returntrue;}}}// unmark the current cell as visitedboard[i][j]=temp;returnfalse;}// find all words in a given grid of charactersfunctionwordBoggle(board,dictionary){letn=board.length;letm=board[0].length;letresult=newSet();letans=[];// try each word from dictionaryfor(letwordofdictionary){// try every starting cell in boardfor(letr=0;r<n;r++){for(letc=0;c<m;c++){if(dfs(board,word,r,c,0))result.add(word);}}}return[...result];}// DRIVER CODEconstdictionary=["GEEKS","FOR","QUIZ","GO"];constboard=[['G','I','Z'],['U','E','K'],['Q','S','E']];letans=wordBoggle(board,dictionary);console.log(ans);
Output
["GEEKS","QUIZ"]
[Expected Approach] Trie + DFS Backtracking - O(n × l + r × c × 8^l) Time and O(n × l + r × c) Space
The idea is to store all dictionary words in a Trie (Prefix Tree) and perform a DFS from every cell of the board. During the traversal, we move through both the board and the Trie simultaneously.
For each cell, we check whether its character exists as a child of the current Trie node. If it does not, the search along that path stops immediately. Otherwise, we continue exploring all 8 adjacent cells. Whenever a Trie node marked as the end of a word is reached, the corresponding word is added to the answer. A visited matrix is used to ensure that a cell is not reused while forming a word, and backtracking restores the state after exploring a path.
Insert all dictionary words into a Trie.
Create a visited matrix of size r × c.
Start DFS from every cell of the board.
For each DFS call, check if the current character exists in the Trie.
Mark the current cell as visited.
If the Trie node is a leaf, add the word to the answer.
Explore all 8 adjacent cells.
Backtrack by unmarking the current cell.
Return all discovered words.
Consider : board[][] = [[G, I, Z], [U, E, K], [Q, S, E]], dictionary[] = ["GEEKS", "FOR", "QUIZ", "GO"]
Step 1: All words are inserted into Trie:
Step 2: DFS Traversal
Start from (0,0) = 'G', 'G' is in Trie, explore path: G -> E -> E -> K -> S, found "GEEKS"
Start from (2,0) = 'Q', 'Q' is in Trie, explore path: Q -> U ->I ->Z, found "QUIZ"
Other DFS paths either do not match any Trie prefix or do not form a complete dictionary word, so they are pruned.
Final Output: ["GEEKS", "QUIZ"]
C++
#include<bits/stdc++.h>usingnamespacestd;// Maximum 26 lowercase + 26 uppercase lettersstaticconstintSIZE=52;// Trie Node DefinitionclassTrieNode{public:TrieNode*child[SIZE];boolleaf;TrieNode(){leaf=false;for(inti=0;i<SIZE;i++)child[i]=NULL;}};// A-Z ? 0-25// a-z ? 26-51staticintgetIndex(charch){if(ch>='A'&&ch<='Z')returnch-'A';if(ch>='a'&&ch<='z')returnch-'a'+26;return-1;}// Insert Word into Triestaticvoidinsert(TrieNode*root,stringword){TrieNode*curr=root;for(charch:word){intidx=getIndex(ch);if(idx==-1)continue;if(curr->child[idx]==NULL)curr->child[idx]=newTrieNode();curr=curr->child[idx];}curr->leaf=true;}// Check valid cellstaticboolisSafe(inti,intj,vector<vector<bool>>&vis,intr,intc){return(i>=0&&i<r&&j>=0&&j<c&&!vis[i][j]);}// DFS on board + Triestaticvoiddfs(TrieNode*node,vector<vector<char>>&board,inti,intj,vector<vector<bool>>&vis,stringpath,vector<string>&res,unordered_set<string>&st,intr,intc){if(!node)return;if(node->leaf){if(st.find(path)==st.end()){st.insert(path);res.push_back(path);}}vis[i][j]=true;intdx[8]={-1,-1,-1,0,0,1,1,1};intdy[8]={-1,0,1,-1,1,-1,0,1};for(intd=0;d<8;d++){intni=i+dx[d];intnj=j+dy[d];if(isSafe(ni,nj,vis,r,c)){charch=board[ni][nj];intidx=getIndex(ch);// validate idxif(idx!=-1&&node->child[idx]!=NULL){dfs(node->child[idx],board,ni,nj,vis,path+ch,res,st,r,c);}}}vis[i][j]=false;}vector<string>wordBoggle(vector<vector<char>>&board,vector<string>&dictionary){vector<string>empty;if(board.empty()||board[0].empty())returnempty;intr=board.size();intc=board[0].size();TrieNode*root=newTrieNode();// Step 1: Build Triefor(stringword:dictionary)insert(root,word);vector<string>res;unordered_set<string>st;vector<vector<bool>>vis(r,vector<bool>(c,false));// Step 2: Start DFS from each cellfor(inti=0;i<r;i++){for(intj=0;j<c;j++){intidx=getIndex(board[i][j]);if(idx!=-1&&root->child[idx]!=NULL){dfs(root->child[idx],board,i,j,vis,string(1,board[i][j]),res,st,r,c);}}}returnres;}intmain(){vector<string>dictionary={"GEEKS","FOR","QUIZ","GO"};vector<vector<char>>board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};vector<string>ans=wordBoggle(board,dictionary);sort(ans.begin(),ans.end());cout<<"[";for(inti=0;i<ans.size();i++){cout<<"\""<<ans[i]<<"\"";if(i!=ans.size()-1)cout<<",";}cout<<"]";return0;}
Java
importjava.util.ArrayList;importjava.util.Arrays;importjava.util.Collections;importjava.util.HashSet;classGFG{staticfinalintSIZE=52;// Trie Node DefinitionstaticclassTrieNode{TrieNode[]child=newTrieNode[SIZE];booleanleaf;TrieNode(){leaf=false;}}// A-Z → 0-25// a-z → 26-51staticintgetIndex(charch){if(ch>='A'&&ch<='Z')returnch-'A';if(ch>='a'&&ch<='z')returnch-'a'+26;return-1;}// Insert Word into Triestaticvoidinsert(TrieNoderoot,Stringword){TrieNodecurr=root;for(charch:word.toCharArray()){intidx=getIndex(ch);if(idx==-1)continue;if(curr.child[idx]==null)curr.child[idx]=newTrieNode();curr=curr.child[idx];}curr.leaf=true;}// Check valid cellstaticbooleanisSafe(inti,intj,boolean[][]vis,intr,intc){return(i>=0&&i<r&&j>=0&&j<c&&!vis[i][j]);}// DFS on board + Triestaticvoiddfs(TrieNodenode,char[][]board,inti,intj,boolean[][]vis,Stringpath,ArrayList<String>res,HashSet<String>st,intr,intc){if(node==null)return;if(node.leaf){if(!st.contains(path)){st.add(path);res.add(path);}}vis[i][j]=true;int[]dx={-1,-1,-1,0,0,1,1,1};int[]dy={-1,0,1,-1,1,-1,0,1};for(intd=0;d<8;d++){intni=i+dx[d];intnj=j+dy[d];if(isSafe(ni,nj,vis,r,c)){charch=board[ni][nj];intidx=getIndex(ch);// validate idxif(idx!=-1&&node.child[idx]!=null){dfs(node.child[idx],board,ni,nj,vis,path+ch,res,st,r,c);}}}vis[i][j]=false;}staticArrayList<String>wordBoggle(char[][]board,String[]dictionary){ArrayList<String>empty=newArrayList<>();if(board.length==0||board[0].length==0)returnempty;intr=board.length;intc=board[0].length;TrieNoderoot=newTrieNode();// Step 1: Build Triefor(Stringword:dictionary)insert(root,word);ArrayList<String>res=newArrayList<>();HashSet<String>st=newHashSet<>();boolean[][]vis=newboolean[r][c];// Step 2: Start DFS from each cellfor(inti=0;i<r;i++){for(intj=0;j<c;j++){intidx=getIndex(board[i][j]);if(idx!=-1&&root.child[idx]!=null){dfs(root.child[idx],board,i,j,vis,String.valueOf(board[i][j]),res,st,r,c);}}}returnres;}publicstaticvoidmain(String[]args){String[]dictionary={"GEEKS","FOR","QUIZ","GO"};char[][]board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};ArrayList<String>ans=wordBoggle(board,dictionary);Collections.sort(ans);System.out.print(ans);}}
Python
classTrieNode:SIZE=52def__init__(self):# child[i] stores reference to next TrieNodeself.child=[None]*TrieNode.SIZE# True if this node represents end of a wordself.leaf=False# Convert character to index (A-Z → 0-25, a-z → 26-51)defgetIndex(ch):if'A'<=ch<='Z':returnord(ch)-ord('A')if'a'<=ch<='z':returnord(ch)-ord('a')+26return-1# Insert a word into Triedefinsert(root,word):curr=rootforchinword:idx=getIndex(ch)# ignore invalid charactersifidx==-1:continue# create node if not presentifcurr.child[idx]isNone:curr.child[idx]=TrieNode()curr=curr.child[idx]# mark end of wordcurr.leaf=True# Check if cell is within bounds and not visiteddefisSafe(i,j,vis,r,c):return0<=i<rand0<=j<candnotvis[i][j]# DFS traversal on board + Trie simultaneouslydefdfs(node,board,i,j,vis,path,res,st,r,c):ifnodeisNone:return# if current Trie node marks end of wordifnode.leafandpathnotinst:st.add(path)res.append(path)# mark current cell as visitedvis[i][j]=True# all 8 possible directionsdx=[-1,-1,-1,0,0,1,1,1]dy=[-1,0,1,-1,1,-1,0,1]# explore neighborsfordinrange(8):ni,nj=i+dx[d],j+dy[d]ifisSafe(ni,nj,vis,r,c):ch=board[ni][nj]idx=getIndex(ch)# move only if Trie path existsifidx!=-1andnode.child[idx]isnotNone:dfs(node.child[idx],board,ni,nj,vis,path+ch,res,st,r,c)# backtrack (unmark visited)vis[i][j]=FalsedefwordBoggle(board,dictionary):# edge case: empty boardifnotboardornotboard[0]:return[]r,c=len(board),len(board[0])# Step 1: Build Trie from dictionaryroot=TrieNode()forwordindictionary:insert(root,word)res=[]st=set()# visited matrix for DFSvis=[[Falsefor_inrange(c)]for_inrange(r)]# Step 2: start DFS from every cellforiinrange(r):forjinrange(c):idx=getIndex(board[i][j])# start DFS only if character exists in Trie rootifidx!=-1androot.child[idx]isnotNone:dfs(root.child[idx],board,i,j,vis,board[i][j],res,st,r,c)returnresif__name__=="__main__":dictionary=["GEEKS","FOR","QUIZ","GO"]board=[['G','I','Z'],['U','E','K'],['Q','S','E']]ans=wordBoggle(board,dictionary)ans.sort()print(ans)
C#
usingSystem;usingSystem.Collections.Generic;publicclassGFG{staticreadonlyintSIZE=52;// Trie Node DefinitionclassTrieNode{publicTrieNode[]child;publicboolleaf;publicTrieNode(){child=newTrieNode[SIZE];leaf=false;}}// A-Z -> 0-25// a-z -> 26-51intgetIndex(charch){if(ch>='A'&&ch<='Z')returnch-'A';if(ch>='a'&&ch<='z')returnch-'a'+26;return-1;}// Insert Word into Trievoidinsert(TrieNoderoot,stringword){TrieNodecurr=root;foreach(charchinword){intidx=getIndex(ch);if(idx==-1)continue;if(curr.child[idx]==null)curr.child[idx]=newTrieNode();curr=curr.child[idx];}curr.leaf=true;}// Check valid cellboolisSafe(inti,intj,bool[,]vis,intr,intc){returni>=0&&i<r&&j>=0&&j<c&&!vis[i,j];}// DFS on board + Trievoiddfs(TrieNodenode,char[,]board,inti,intj,bool[,]vis,stringpath,List<string>res,HashSet<string>st,intr,intc){if(node.leaf){if(!st.Contains(path)){st.Add(path);res.Add(path);}}vis[i,j]=true;int[]dx={-1,-1,-1,0,0,1,1,1};int[]dy={-1,0,1,-1,1,-1,0,1};for(intd=0;d<8;d++){intni=i+dx[d];intnj=j+dy[d];if(isSafe(ni,nj,vis,r,c)){charch=board[ni,nj];intidx=getIndex(ch);if(idx!=-1&&node.child[idx]!=null){dfs(node.child[idx],board,ni,nj,vis,path+ch,res,st,r,c);}}}vis[i,j]=false;}publicList<string>wordBoggle(char[,]board,string[]dictionary){intr=board.GetLength(0);intc=board.GetLength(1);TrieNoderoot=newTrieNode();// Step 1: Build Trieforeach(stringwordindictionary)insert(root,word);List<string>res=newList<string>();HashSet<string>st=newHashSet<string>();bool[,]vis=newbool[r,c];// Step 2: Start DFS from each cellfor(inti=0;i<r;i++){for(intj=0;j<c;j++){intidx=getIndex(board[i,j]);if(idx!=-1&&root.child[idx]!=null){dfs(root.child[idx],board,i,j,vis,board[i,j].ToString(),res,st,r,c);}}}returnres;}publicstaticvoidMain(){string[]dictionary={"GEEKS","FOR","QUIZ","GO"};char[,]board={{'G','I','Z'},{'U','E','K'},{'Q','S','E'}};GFGobj=newGFG();List<string>ans=obj.wordBoggle(board,dictionary);ans.Sort();Console.Write("[");for(inti=0;i<ans.Count;i++){Console.Write("\""+ans[i]+"\"");if(i!=ans.Count-1)Console.Write(",");}Console.Write("]");}}
JavaScript
// Trie Node DefinitionclassTrieNode{constructor(){this.child=Array.from({length:52},()=>null);this.leaf=false;}}// Map character to index (A-Z: 0-25, a-z: 26-51)functiongetIndex(ch){if(ch>='A'&&ch<='Z')returnch.charCodeAt(0)-'A'.charCodeAt(0);if(ch>='a'&&ch<='z')returnch.charCodeAt(0)-'a'.charCodeAt(0)+26;return-1;}// Insert word into Triefunctioninsert(root,word){letcurr=root;for(letchofword){letidx=getIndex(ch);if(idx===-1)continue;if(!curr.child[idx])curr.child[idx]=newTrieNode();curr=curr.child[idx];}curr.leaf=true;}// Check valid grid cellfunctionisSafe(i,j,vis,r,c){returni>=0&&i<r&&j>=0&&j<c&&!vis[i][j];}// DFS with Trie traversalfunctiondfs(node,board,i,j,vis,path,res,set,r,c){if(!node)return;// If word foundif(node.leaf){if(!set.has(path)){set.add(path);res.push(path);}}vis[i][j]=true;// Explore 8 directionsletdx=[-1,-1,-1,0,0,1,1,1];letdy=[-1,0,1,-1,1,-1,0,1];for(letd=0;d<8;d++){letni=i+dx[d];letnj=j+dy[d];if(isSafe(ni,nj,vis,r,c)){letch=board[ni][nj];letidx=getIndex(ch);if(idx!==-1&&node.child[idx]){dfs(node.child[idx],board,ni,nj,vis,path+ch,res,set,r,c);}}}vis[i][j]=false;}functionwordBoggle(board,dictionary){if(!board.length||!board[0].length)return[];letr=board.length;letc=board[0].length;// Build Trie from dictionaryletroot=newTrieNode();for(letwordofdictionary)insert(root,word);letres=[];letset=newSet();letvis=Array.from({length:r},()=>Array(c).fill(false));// Start DFS from every cellfor(leti=0;i<r;i++){for(letj=0;j<c;j++){letidx=getIndex(board[i][j]);if(idx!==-1&&root.child[idx]){dfs(root.child[idx],board,i,j,vis,board[i][j],res,set,r,c);}}}returnres;}// Driver codeconstdictionary=["GEEKS","FOR","QUIZ","GO"];constboard=[['G','I','Z'],['U','E','K'],['Q','S','E']];letans=wordBoggle(board,dictionary);ans.sort();process.stdout.write("["+ans.map(w=>`"${w}"`).join(",")+"]");