diff --git a/README.md b/README.md index 23aaf3c..991e485 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ | Current Status| Stats | | :------------: | :----------: | -| Total Problems | 186 | +| Total Problems | 187 | @@ -219,6 +219,7 @@ Include contains single header implementation of data structures and some algori | :------------ | :----------: | | You are given a digit string (e.g "1234", "567" etc), provide all possible letter combinations we could generate from this digit string, based on the mapping we see on the telphone/mobile dialpad. If you have typed SMS in old style phones, you would know. For e.g. "1" is mapped to "abc", 2 is mapped to "def". You can refer to the image.. Note that order does not matter in result set.|[dialpad_combinations.cpp](backtracking_problems/dialpad_combinations.cpp)| | Implement wildcard pattern maching with support for '?' & '*'. . Checkout examples in file for more details.|[wild_card_matching.cpp](backtracking_problems/wild_card_matching.cpp)| +| Given a 2D board and list of words from a dictionary, find all the possible words on board fromt the list. (Check example in the solution)| [word_search.cpp](backtracking_problems/word_search.cpp)| diff --git a/backtracking_problems/word_search.cpp b/backtracking_problems/word_search.cpp new file mode 100644 index 0000000..9b51627 --- /dev/null +++ b/backtracking_problems/word_search.cpp @@ -0,0 +1,142 @@ +/* + * Given a 2D board and list of words from a dictionary, + * find all the possible words on board fromt the list. + * Example: + * words = ["oath","pea","eat","rain"] + * board = + * [ + * ['o','a','a','n'], + * ['e','t','a','e'], + * ['i','h','k','r'], + * ['i','f','l','v'] + * ] + * + * Output: ["eat", "oath"] + * + * Source : LeetCode Problem 212 + * + * Approach: + * + * We can use backtracking(dfs) to traverse from each character on board + * to all four direction. In order to do a fast searching, we can use + * a trie from words in dictionary, as soon as we find a word from dictionary + * in trie, we remove it from trie, so we don't have duplicates. + * Also, we can use the board to mark '#' as visited character to + * achieve backtracking. + */ + +#include +#include + +struct TrieNode { + std::string word; + std::vector children; + TrieNode(): + word{""}, children{std::vector(26, nullptr)}{} +}; + +TrieNode* build_trie(const std::vector& dictionary) +{ + TrieNode* root = new TrieNode(); + for (auto word: dictionary) { + TrieNode* curr = root; + for (auto c: word) { + int index = c - 'a'; + if (curr->children[index] == nullptr) { + curr->children[index] = new TrieNode(); + } + curr = curr->children[index]; + } + curr->word = word; + } + return root; +} + +void backtrack(std::vector>& board, + TrieNode* root, int i, int j, std::vector& result) +{ + char c = board[i][j]; + if (c == '#' || root == nullptr) { + return; + } + int index = c - 'a'; + TrieNode* curr = root->children[index]; + if (curr == nullptr) { + return; + } + + if (curr->word != "") { + result.push_back(curr->word); + // Reset to avoid duplicates. + curr->word = ""; + } + + board[i][j] = '#'; + if (i > 0) { + backtrack(board, curr, i - 1, j, result); + } + if (j > 0) { + backtrack(board, curr, i, j - 1, result); + } + if (i < board.size() - 1) { + backtrack(board, curr, i + 1, j, result); + } + if (j < board[0].size() - 1) { + backtrack(board, curr, i, j + 1, result); + } + board[i][j] = c; +} + +std::vector find_words(std::vector>& board, + std::vector& dictionary) +{ + std::vector result; + for (int i = 0; i < board.size(); ++i) { + for (int j = 0; j < board[0].size(); ++j) { + TrieNode* root = build_trie(dictionary); + backtrack(board, root, i, j, result); + } + } + return result; +} + +template +void print_vector(const std::vector& vec) +{ + std::cout << "{ "; + for (auto t : vec) { + std::cout << t << " "; + } + std::cout << " }" << std::endl; +} + +void print_board(const std::vector>& board) +{ + for (auto v: board) { + print_vector(v); + } +} + + +int main() +{ + std::vector> board = { + {'o','a','a','n'}, + {'e','t','a','e'}, + {'i','h','k','r'}, + {'i','f','l','v'} + }; + + std::vector dictionary = { + "oath","pea","eat","rain" + }; + + std::vector result = find_words(board, dictionary); + std::cout << "Board:" << std::endl; + print_board(board); + std::cout << "Dictionary:" << std::endl; + print_vector(dictionary); + std::cout << "Result:" << std::endl; + print_vector(result); + return 0; +}