You are given a list of strings, words[], and an n × m matrix of characters, letters[][]. The objective is to locate all the words from words[] that can be constructed by consecutively linking adjacent characters in the matrix. You are allowed to move in any of the 8 possible directions (horizontally, vertically, or diagonally), but each cell in the matrix can be used only once per word.
Example:
Input: words[] = [ "geeks", "for", "quiz", "go" ]
letters[][] = [[ 'g', 'i', 'z' ],
[ 'u', 'e', 'k' ],
[ 'q', 's', 'e' ]]
Output: geeks quiz
Explanation: To form the word "geeks", begin at cell (0,0) containing 'g'. Next, proceed diagonally down-right to cell (1,1) with 'e', then continue in the same diagonal direction to cell (2,2) for another 'e'. After that, move upward to cell (1,2) to pick up 'k', and finally, go diagonally down-left to cell (2,1) to complete the word with 's'.
Table of Content
[Naive Approach] - Using Depth First Search - O(n ^ 2 * m ^ 2) Time and O(n * m) 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.
Below is given the implementation:
#include <bits/stdc++.h>
using namespace std;
// function to perform dfs on the grid
void dfs(vector<vector<char>>& letters,
vector<vector<bool>>& visited,
int i, int j, string &str,
unordered_set<string>& wordSet,
vector<string>& ans) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.size() ||
j < 0 || j >= letters[0].size()) {
return;
}
// check if the current cell is already visited
if (visited[i][j]) {
return;
}
// mark the current cell as visited
visited[i][j] = true;
// add the current character to the string
str += letters[i][j];
// check if the current string is in the wordSet
if (wordSet.find(str) != wordSet.end()) {
ans.push_back(str);
// remove the word from the set to avoid duplicates
wordSet.erase(str);
}
// perform dfs on all 8 directions
for (int row = -1; row <= 1; row++) {
for (int col = -1; col <= 1; col++) {
// skip the current cell
if (row == 0 && col == 0) continue;
dfs(letters, visited, i + row,
j + col, str, wordSet, ans);
}
}
// backtrack and unmark the current cell as visited
visited[i][j] = false;
// remove the last character from the string
str.pop_back();
}
// find all words in a given grid of characters
// and a given dictionary
vector<string> findWords(vector<string>& words,
vector<vector<char>>& letters) {
int n = letters.size(), m = letters[0].size();
vector<string> ans;
// store the words in the hashSet
unordered_set<string> wordSet(words.begin(), words.end());
// to mark the cell visited
vector<vector<bool>> visited(n, vector<bool>(m, false));
// perform dfs on each cell of the grid
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
string str = "";
dfs(letters, visited, i, j, str, wordSet, ans);
}
}
return ans;
}
int main() {
vector<string> words = {"geeks", "for", "quiz", "go"};
vector<vector<char>> letters = {
{'g', 'i', 'z'},
{'u', 'e', 'k'},
{'q', 's', 'e'}
};
vector<string> ans = findWords(words, letters);
for (string word : ans) {
cout << word << " ";
}
return 0;
}
import java.util.*;
class GfG {
// function to perform dfs on the grid
static void dfs(char[][] letters,
boolean[][] visited,
int i, int j, StringBuilder str,
Set<String> wordSet,
List<String> ans) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.length ||
j < 0 || j >= letters[0].length) {
return;
}
// check if the current cell is already visited
if (visited[i][j]) {
return;
}
// mark the current cell as visited
visited[i][j] = true;
// add the current character to the string
str.append(letters[i][j]);
// check if the current string is in the wordSet
if (wordSet.contains(str.toString())) {
ans.add(str.toString());
// remove the word from the set to avoid duplicates
wordSet.remove(str.toString());
}
// perform dfs on all 8 directions
for (int row = -1; row <= 1; row++) {
for (int col = -1; col <= 1; col++) {
// skip the current cell
if (row == 0 && col == 0) continue;
dfs(letters, visited, i + row,
j + col, str, wordSet, ans);
}
}
// backtrack and unmark the current cell as visited
visited[i][j] = false;
// remove the last character from the string
str.deleteCharAt(str.length() - 1);
}
// find all words in a given grid of characters
// and a given dictionary
static List<String> findWords(List<String> words,
char[][] letters) {
int n = letters.length, m = letters[0].length;
List<String> ans = new ArrayList<>();
// store the words in the hashSet
Set<String> wordSet = new HashSet<>(words);
// to mark the cell visited
boolean[][] visited = new boolean[n][m];
// perform dfs on each cell of the grid
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
StringBuilder str = new StringBuilder();
dfs(letters, visited, i, j, str, wordSet, ans);
}
}
return ans;
}
public static void main(String[] args) {
List<String> words = Arrays.asList("geeks", "for", "quiz", "go");
char[][] letters = {
{'g', 'i', 'z'},
{'u', 'e', 'k'},
{'q', 's', 'e'}
};
List<String> ans = findWords(words, letters);
for (String word : ans) {
System.out.print(word + " ");
}
}
}
# function to perform dfs on the grid
def dfs(letters, visited, i, j, str, wordSet, ans):
# check if the current cell is out of bounds
if i < 0 or i >= len(letters) or j < 0 or j >= len(letters[0]):
return
# check if the current cell is already visited
if visited[i][j]:
return
# mark the current cell as visited
visited[i][j] = True
# add the current character to the string
str += letters[i][j]
# check if the current string is in the wordSet
if str in wordSet:
ans.append(str)
# remove the word from the set to avoid duplicates
wordSet.remove(str)
# perform dfs on all 8 directions
for row in range(-1, 2):
for col in range(-1, 2):
# skip the current cell
if row == 0 and col == 0:
continue
dfs(letters, visited, i + row, j + col, str, wordSet, ans)
# backtrack and unmark the current cell as visited
visited[i][j] = False
# remove the last character from the string
str = str[:-1]
# find all words in a given grid of characters
# and a given dictionary
def findWords(words, letters):
n, m = len(letters), len(letters[0])
ans = []
# store the words in the hashSet
wordSet = set(words)
# to mark the cell visited
visited = [[False for _ in range(m)] for _ in range(n)]
# perform dfs on each cell of the grid
for i in range(n):
for j in range(m):
dfs(letters, visited, i, j, "", wordSet, ans)
return ans
words = ["geeks", "for", "quiz", "go"]
letters = [
['g', 'i', 'z'],
['u', 'e', 'k'],
['q', 's', 'e']
]
ans = findWords(words, letters)
for word in ans:
print(word, end=" ")
using System;
using System.Collections.Generic;
class GfG {
// function to perform dfs on the grid
static void dfs(char[,] letters,
bool[,] visited,
int i, int j, string str,
HashSet<string> wordSet,
List<string> ans) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.GetLength(0) ||
j < 0 || j >= letters.GetLength(1)) {
return;
}
// check if the current cell is already visited
if (visited[i, j]) {
return;
}
// mark the current cell as visited
visited[i, j] = true;
// add the current character to the string
str += letters[i, j];
// check if the current string is in the wordSet
if (wordSet.Contains(str)) {
ans.Add(str);
// remove the word from the set to avoid duplicates
wordSet.Remove(str);
}
// perform dfs on all 8 directions
for (int row = -1; row <= 1; row++) {
for (int col = -1; col <= 1; col++) {
// skip the current cell
if (row == 0 && col == 0) continue;
dfs(letters, visited, i + row,
j + col, str, wordSet, ans);
}
}
// backtrack and unmark the current cell as visited
visited[i, j] = false;
// remove the last character from the string
str = str.Substring(0, str.Length - 1);
}
// find all words in a given grid of characters
// and a given dictionary
static List<string> findWords(List<string> words,
char[,] letters) {
int n = letters.GetLength(0), m = letters.GetLength(1);
List<string> ans = new List<string>();
// store the words in the hashSet
HashSet<string> wordSet = new HashSet<string>(words);
// to mark the cell visited
bool[,] visited = new bool[n, m];
// perform dfs on each cell of the grid
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
dfs(letters, visited, i, j, "", wordSet, ans);
}
}
return ans;
}
static void Main() {
List<string> words = new List<string>{"geeks", "for", "quiz", "go"};
char[,] letters = {
{'g', 'i', 'z'},
{'u', 'e', 'k'},
{'q', 's', 'e'}
};
List<string> ans = findWords(words, letters);
foreach (string word in ans) {
Console.Write(word + " ");
}
}
}
// function to perform dfs on the grid
function dfs(letters, visited, i, j, str, wordSet, ans) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.length || j < 0 || j >= letters[0].length) {
return;
}
// check if the current cell is already visited
if (visited[i][j]) {
return;
}
// mark the current cell as visited
visited[i][j] = true;
// add the current character to the string
str += letters[i][j];
// check if the current string is in the wordSet
if (wordSet.has(str)) {
ans.push(str);
// remove the word from the set to avoid duplicates
wordSet.delete(str);
}
// perform dfs on all 8 directions
for (let row = -1; row <= 1; row++) {
for (let col = -1; col <= 1; col++) {
// skip the current cell
if (row === 0 && col === 0) continue;
dfs(letters, visited, i + row, j + col, str, wordSet, ans);
}
}
// backtrack and unmark the current cell as visited
visited[i][j] = false;
// remove the last character from the string
str = str.slice(0, -1);
}
// find all words in a given grid of characters
// and a given dictionary
function findWords(words, letters) {
const n = letters.length, m = letters[0].length;
const ans = [];
// store the words in the hashSet
const wordSet = new Set(words);
// to mark the cell visited
const visited = Array.from({ length: n }, () => Array(m).fill(false));
// perform dfs on each cell of the grid
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
dfs(letters, visited, i, j, "", wordSet, ans);
}
}
return ans;
}
const words = ["geeks", "for", "quiz", "go"];
const letters = [
['g', 'i', 'z'],
['u', 'e', 'k'],
['q', 's', 'e']
];
const ans = findWords(words, letters);
console.log(ans.join(" "));
Output
geeks quiz
[Better Approach] - Using Depth First Search - O(n * m + r * c) Time and O(n * m) Space
Instead of generating all strings from the grid and then checking whether it exists in dictionary or not , we can simply run a DFS on all words present in dictionary and check whether we can make that word from grid or not.
Below is given the implementation:
#include <bits/stdc++.h>
using namespace std;
// function to perform dfs on the grid
bool dfs(vector<vector<char>>& letters,
string word, int i, int j, int index) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.size() || j < 0 || j >= letters[0].size()) {
return false;
}
// check if the current cell matches
// the character in the word
if (letters[i][j] != word[index]) {
return false;
}
// check if we have found the complete word
if (index == word.size() - 1) {
return true;
}
// mark the current cell as visited
char temp = letters[i][j];
letters[i][j] = '#';
// perform dfs on all 8 directions
for(int row = -1; row <= 1; row++) {
for (int col = -1; col <= 1; col++) {
// skip the current cell
if (row == 0 && col == 0) continue;
if (dfs(letters, word, i + row, j + col, index + 1)) {
// unmark the current cell as visited
letters[i][j] = temp;
return true;
}
}
}
// unmark the current cell as visited
letters[i][j] = temp;
return false;
}
// find all words in a given grid of characters
// and a given dictionary
vector<string> findWords(vector<string>& words,
vector<vector<char>>& letters) {
int n = letters.size(), m = letters[0].size();
int r = words.size();
vector<string> ans;
// store the unique words in the hashSet
unordered_set<string> result;
for(int i = 0; i < r; i++) {
for(int j = 0; j < n; j++) {
for(int k = 0; k < m; k++) {
if(dfs(letters, words[i], j, k, 0)) {
result.insert(words[i]);
}
}
}
}
// convert the set to vector
for(auto word : result) {
ans.push_back(word);
}
return ans;
}
int main() {
vector<string> words = {"geeks", "for", "quiz", "go"};
vector<vector<char>> letters = {
{'g', 'i', 'z'},
{'u', 'e', 'k'},
{'q', 's', 'e'}
};
vector<string> ans = findWords(words, letters);
for (string word : ans) {
cout << word << " ";
}
return 0;
}
import java.util.*;
class GfG {
// function to perform dfs on the grid
static boolean dfs(char[][] letters,
String word, int i, int j, int index) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.length || j < 0 || j >= letters[0].length) {
return false;
}
// check if the current cell matches
// the character in the word
if (letters[i][j] != word.charAt(index)) {
return false;
}
// check if we have found the complete word
if (index == word.length() - 1) {
return true;
}
// mark the current cell as visited
char temp = letters[i][j];
letters[i][j] = '#';
// perform dfs on all 8 directions
for (int row = -1; row <= 1; row++) {
for (int col = -1; col <= 1; col++) {
// skip the current cell
if (row == 0 && col == 0) continue;
if (dfs(letters, word, i + row, j + col, index + 1)) {
// unmark the current cell as visited
letters[i][j] = temp;
return true;
}
}
}
// unmark the current cell as visited
letters[i][j] = temp;
return false;
}
// find all words in a given grid of characters
// and a given dictionary
static List<String> findWords(List<String> words,
char[][] letters) {
int n = letters.length, m = letters[0].length;
int r = words.size();
List<String> ans = new ArrayList<>();
// store the unique words in the hashSet
Set<String> result = new HashSet<>();
for (int i = 0; i < r; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) {
if (dfs(letters, words.get(i), j, k, 0)) {
result.add(words.get(i));
}
}
}
}
// convert the set to vector
for (String word : result) {
ans.add(word);
}
return ans;
}
public static void main(String[] args) {
List<String> words = Arrays.asList("geeks", "for", "quiz", "go");
char[][] letters = {
{'g', 'i', 'z'},
{'u', 'e', 'k'},
{'q', 's', 'e'}
};
List<String> ans = findWords(words, letters);
for (String word : ans) {
System.out.print(word + " ");
}
}
}
# function to perform dfs on the grid
def dfs(letters, word, i, j, index):
# check if the current cell is out of bounds
if i < 0 or i >= len(letters) or j < 0 or j >= len(letters[0]):
return False
# check if the current cell matches
# the character in the word
if letters[i][j] != word[index]:
return False
# check if we have found the complete word
if index == len(word) - 1:
return True
# mark the current cell as visited
temp = letters[i][j]
letters[i][j] = '#'
# perform dfs on all 8 directions
for row in range(-1, 2):
for col in range(-1, 2):
# skip the current cell
if row == 0 and col == 0:
continue
if dfs(letters, word, i + row, j + col, index + 1):
# unmark the current cell as visited
letters[i][j] = temp
return True
# unmark the current cell as visited
letters[i][j] = temp
return False
# find all words in a given grid of characters
# and a given dictionary
def findWords(words, letters):
n, m = len(letters), len(letters[0])
r = len(words)
ans = []
# store the unique words in the hashSet
result = set()
for i in range(r):
for j in range(n):
for k in range(m):
if dfs(letters, words[i], j, k, 0):
result.add(words[i])
# convert the set to vector
for word in result:
ans.append(word)
return ans
words = ["geeks", "for", "quiz", "go"]
letters = [
['g', 'i', 'z'],
['u', 'e', 'k'],
['q', 's', 'e']
]
ans = findWords(words, letters)
for word in ans:
print(word, end=' ')
using System;
using System.Collections.Generic;
class GfG {
// function to perform dfs on the grid
static bool dfs(char[][] letters,
string word, int i, int j, int index) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.Length || j < 0
|| j >= letters[0].Length) {
return false;
}
// check if the current cell matches
// the character in the word
if (letters[i][j] != word[index]) {
return false;
}
// check if we have found the complete word
if (index == word.Length - 1) {
return true;
}
// mark the current cell as visited
char temp = letters[i][j];
letters[i][j] = '#';
// perform dfs on all 8 directions
for (int row = -1; row <= 1; row++) {
for (int col = -1; col <= 1; col++) {
// skip the current cell
if (row == 0 && col == 0) continue;
if (dfs(letters, word, i + row, j + col, index + 1)) {
// unmark the current cell as visited
letters[i][j] = temp;
return true;
}
}
}
// unmark the current cell as visited
letters[i][j] = temp;
return false;
}
// find all words in a given grid of characters
// and a given dictionary
static List<string> findWords(List<string> words,
char[][] letters) {
int n = letters.Length, m = letters[0].Length;
int r = words.Count;
List<string> ans = new List<string>();
// store the unique words in the hashSet
HashSet<string> result = new HashSet<string>();
for (int i = 0; i < r; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < m; k++) {
if (dfs(letters, words[i], j, k, 0)) {
result.Add(words[i]);
}
}
}
}
// convert the set to vector
foreach (string word in result) {
ans.Add(word);
}
return ans;
}
static void Main() {
List<string> words = new List<string>{"geeks", "for", "quiz", "go"};
char[][] letters = {
new char[]{'g', 'i', 'z'},
new char[]{'u', 'e', 'k'},
new char[]{'q', 's', 'e'}
};
List<string> ans = findWords(words, letters);
foreach (string word in ans) {
Console.Write(word + " ");
}
}
}
// function to perform dfs on the grid
function dfs(letters, word, i, j, index) {
// check if the current cell is out of bounds
if (i < 0 || i >= letters.length || j < 0 || j >= letters[0].length) {
return false;
}
// check if the current cell matches
// the character in the word
if (letters[i][j] !== word[index]) {
return false;
}
// check if we have found the complete word
if (index === word.length - 1) {
return true;
}
// mark the current cell as visited
let temp = letters[i][j];
letters[i][j] = '#';
// perform dfs on all 8 directions
for (let row = -1; row <= 1; row++) {
for (let col = -1; col <= 1; col++) {
// skip the current cell
if (row === 0 && col === 0) continue;
if (dfs(letters, word, i + row, j + col, index + 1)) {
// unmark the current cell as visited
letters[i][j] = temp;
return true;
}
}
}
// unmark the current cell as visited
letters[i][j] = temp;
return false;
}
// find all words in a given grid of characters
// and a given dictionary
function findWords(words, letters) {
let n = letters.length, m = letters[0].length;
let r = words.length;
let ans = [];
// store the unique words in the hashSet
let result = new Set();
for (let i = 0; i < r; i++) {
for (let j = 0; j < n; j++) {
for (let k = 0; k < m; k++) {
if (dfs(letters, words[i], j, k, 0)) {
result.add(words[i]);
}
}
}
}
// convert the set to vector
for (let word of result) {
ans.push(word);
}
return ans;
}
let words = ["geeks", "for", "quiz", "go"];
let letters = [
['g', 'i', 'z'],
['u', 'e', 'k'],
['q', 's', 'e']
];
let ans = findWords(words, letters);
for (let word of ans) {
process.stdout.write(word + " ");
}
Output
quiz geeks
Related Article:
