# 79. Word Search Difficulty: Medium ## Solution ```cpp= /** *** Author: R-CO *** E-mail: daniel1820kobe@gmail.com *** Date: 2020-08-28 **/ #include <cstdlib> #include <iostream> #include <stack> #include <string> #include <vector> using namespace std; #define VERSION_1 0 #define VERSION_2 0 #define VERSION_3 1 struct TestCaseStruct { struct Input { vector<vector<char>> board; string word; } input; bool expected_output; }; #if VERSION_1 struct Position { Position(int i, int j) { this->i = i; this->j = j; this->next_direction = 0; } Position(int i, int j, int next_direction) { this->i = i; this->j = j; this->next_direction = next_direction; } int i; int j; int next_direction; }; // non-recursive, but with BUG class Solution { public: bool exist(vector<vector<char>>& board, string word) { vector<vector<int>> used(board.size(), vector<int>(board[0].size(), 0)); for (int i = 0; i < board.size(); ++i) { for (int j = 0; j < board[i].size(); ++j) { size_t index = 0; if (board[i][j] == word[index++]) { used[i][j] = 1; stack<Position> s; s.emplace(Position(i, j, -1)); while (index < word.size()) { auto current_index = index; auto& current_position = s.top(); ++current_position.next_direction; Position adjecent[] = { {current_position.i - 1, current_position.j}, {current_position.i, current_position.j + 1}, {current_position.i + 1, current_position.j}, {current_position.i, current_position.j - 1}}; for (int next_direction = current_position.next_direction; next_direction < 4; ++next_direction) { const auto& next = adjecent[next_direction]; if (next.i < 0 || next.i >= board.size() || next.j < 0 || next.j >= board[i].size()) { continue; } if (used[next.i][next.j] == 1 || board[next.i][next.j] != word[index]) { continue; } used[next.i][next.j] = 1; s.emplace(Position(next.i, next.j, -1)); ++index; break; } if (index == current_index) { used[current_position.i][current_position.j] = 0; --index; s.pop(); if (s.empty()) { break; // break "while (index < word.size())" } } } if (index == word.size()) { return true; } used[i][j] = 0; } } } return false; } }; #endif #if VERSION_2 struct Point { Point(int i, int j) { this->i = i; this->j = j; } int i; int j; }; class Solution { public: bool exist(vector<vector<char>>& board, string word) { // board is m*n m_ = board.size(); n_ = board[0].size(); word_size_ = word.size(); Point current_point(0, 0); for (current_point.i = 0; current_point.i < m_; ++current_point.i) { for (current_point.j = 0; current_point.j < n_; ++current_point.j) { size_t word_index = 0; if (board[current_point.i][current_point.j] == word[word_index]) { if (FindRecursively(board, word, current_point, word_index)) { return true; } } } } return false; } private: bool FindRecursively(vector<vector<char>>& board, const string& word, Point current_point, size_t word_index) { if (++word_index >= word_size_) { return true; } char current_point_symbol = board[current_point.i][current_point.j]; board[current_point.i][current_point.j] = '\0'; vector<Point> adjecent_points = {{current_point.i - 1, current_point.j}, {current_point.i, current_point.j + 1}, {current_point.i + 1, current_point.j}, {current_point.i, current_point.j - 1}}; for (const auto& point : adjecent_points) { /*if (point.i < 0 || point.i >= m_ || point.j < 0 || point.j >= n_) { continue; } if (board[point.i][point.j] == '\0' || board[point.i][point.j] != word[word_index]) { continue; } if (FindRecursively(board, word, point, word_index)) { return true; }*/ if ((point.i >= 0 && point.i < m_ && point.j >= 0 && point.j < n_) && board[point.i][point.j] != '\0' && board[point.i][point.j] == word[word_index]) { if (FindRecursively(board, word, point, word_index)) { board[current_point.i][current_point.j] = current_point_symbol; return true; } } } board[current_point.i][current_point.j] = current_point_symbol; return false; } // board is m*n size_t m_; size_t n_; size_t word_size_; }; #endif #if VERSION_3 struct Point { Point(int i, int j) { this->i = i; this->j = j; } int i; int j; }; class Solution { public: bool exist(vector<vector<char>>& board, string word) { // board is m*n m_ = board.size(); n_ = board[0].size(); Point current_point(0, 0); for (current_point.i = 0; current_point.i < m_; ++current_point.i) { for (current_point.j = 0; current_point.j < n_; ++current_point.j) { const char* w = word.c_str(); if (board[current_point.i][current_point.j] == *w) { if (FindRecursively(board, w, current_point)) { return true; } } } } return false; } private: bool FindRecursively(vector<vector<char>>& board, const char* w, const Point& current_point) { if (*(++w) == '\0') { return true; } char current_point_symbol = board[current_point.i][current_point.j]; board[current_point.i][current_point.j] = '\0'; vector<Point> adjecent_points{{current_point.i - 1, current_point.j}, {current_point.i, current_point.j + 1}, {current_point.i + 1, current_point.j}, {current_point.i, current_point.j - 1}}; for (const auto& point : adjecent_points) { if ((point.i >= 0 && point.i < m_ && point.j >= 0 && point.j < n_) && board[point.i][point.j] != '\0' && board[point.i][point.j] == *w) { if (FindRecursively(board, w, point)) { board[current_point.i][current_point.j] = current_point_symbol; return true; } } } board[current_point.i][current_point.j] = current_point_symbol; return false; } // board is m*n size_t m_; size_t n_; }; #endif int main(int argc, char* argv[]) { /* board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ] Given word = "ABCCED", return true. Given word = "SEE", return true. Given word = "ABCB", return false. board2 = [ ['a', 'b'], ['c', 'd'] ] Given word = "dbac", return true. [["b","a","a","b","a","b"], ["a","b","a","a","a","a"], ["a","b","a","a","a","b"], ["a","b","a","b","b","a"], ["a","a","b","b","a","b"], ["a","a","b","b","b","a"], ["a","a","b","a","a","b"] ] "ababaababaaabbabbaabbaabbaba", return true. */ const vector<vector<char>> board = { {'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}}; const vector<vector<char>> board2 = {{'a', 'b'}, {'c', 'd'}}; const vector<vector<char>> board3 = { {'b', 'a', 'a', 'b', 'a', 'b'}, {'a', 'b', 'a', 'a', 'a', 'a'}, {'a', 'b', 'a', 'a', 'a', 'b'}, {'a', 'b', 'a', 'b', 'b', 'a'}, {'a', 'a', 'b', 'b', 'a', 'b'}, {'a', 'a', 'b', 'b', 'b', 'a'}, {'a', 'a', 'b', 'a', 'a', 'b'}}; TestCaseStruct test_cases[] = { {{board, "ABCCED"}, true}, {{board, "SEE"}, true}, {{board, "ABCB"}, false}, {{board2, "dbac"}, true}, {{board3, "ababaababaaabbabbaabbaabbaba"}, true}}; Solution solution; for (auto& test_case : test_cases) { if (solution.exist(test_case.input.board, test_case.input.word) == test_case.expected_output) { cout << "test case = [" << test_case.input.word << "] is pass." << std::endl; } else { cout << "test case = [" << test_case.input.word << "] is fail." << std::endl; } } return EXIT_SUCCESS; } ``` ## Result Success Details Runtime: 100 ms, faster than 58.07% of C++ online submissions for Word Search. Memory Usage: 19.3 MB, less than 53.49% of C++ online submissions for Word Search. ###### tags: `LeetCode-Medium` `C++`