Word Search II
LeetCode Problem #212 (Hard)
Problem Statement
Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cells, where "adjacent" cells are those horizontally or vertically neighbouring. The same letter cell may not be used more than once in a word.
Testcases
Prerequisite Knowledge
Depth-First-Search
Refer to the Prerequisite Knowledge section in Surrounded Regions:
Trie
A trie is an advanced data structure which is used to solve a very specific type of problem—representing and retrieving words.
In fact, the name "trie" is derived from the word "retrieve". The structure of a trie resembles that of a tree data structure, but for the purposes of distinction and avoiding confusion, "trie" is pronounced as "try".
A trie is unique in its ability to efficiently store and search for words that may be formed using the same prefixes.
In this tree, we can see that the words "that"
, "there"
, and "this"
have the same prefix—"th"
. Instead of storing the letters of each word in separate spatial locations, the words are built based on pre-existing letters in the tree i.e. prefixes of existing words. For this reason, the trie data structure is also known as a "prefix tree".
Structure of a Trie
Each trie has a root node which is the starting point of the trie. The root node has links or references to every unique letter that can be possibly stored. Considering the English alphabet, this means that the root node can have 26 references or 26 child nodes from which words can be constructed.
However, other languages have alphabets of varying size, with some even having twice as many letters as the English alphabet or more. The size of the trie proportionally increases with the number of alphabetic values in the language being represented. This means that we might have to make a trade-off in terms of space complexity when we use tries, even if we benefit from the run-time efficiency.
References
For more information, detailed explanations, and notes on implementation refer to the links below:
Algorithm
Depth-First-Search Approach
In this approach, we use DFS to check the adjacent cells in the board to see if a word can be constructed using the letters in the cell. Although this approach does not require an extensive amount of space, it is very expensive in terms of execution time.
Identify the unique words from the given list of words using a set.
Iterate through each word in the list.
Check if the word exists on the board.
a. Iterate through each cell on the board.
b. Perform DFS from each letter to see if the word can be constructed.
DFS Helper Function
Mark the letters that have already been visited.
Iteratively check the adjacent nodes to see if a word can be constructed.
If the required word is found, return true. Otherwise, return false and check for other words.
Reference:
Time Complexity: O(m*n*4^L)
Trie Approach
This is a significantly more efficient approach, albeit the compromise made in terms of space requirements. We construct a trie using the given list of words. DFS is performed only if there is an existing path indicated by a branch in the trie. If no path exists, we do not have to explore that particular branch.
Build the trie from the given list of words.
Iterate through each cell of the board using DFS and search for the letters needed to form a word.
Construct Word Function
Iterate through each letter of each word in the given list.
If the letter does not exist in the trie already, add it to the appropriate branch of the trie.
Store the letters and words in the trie structure.
DFS Helper Function
If the node has already been visited, return.
Recursively check each adjacent cell on the board to see if the letters will form a word from the given list.
Mark the node that has already been visited.
If a word has successfully been constructed, add it to the resultant vector.
Time Complexity: O(L+4^L)
Code
DFS Approach
Trie Approach
Last updated
Was this helpful?