LeetCode | 79. 单词搜索
原题(Medium):
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
思路:回溯
建立一个xy坐标系,通过4个坐标实现在网格中上下左右地逐格移动,而判断能否移动的条件自然就是:是否越界(要大于等于0,小于网格大小)。另外需一个二维访问数组与网格对标,记录网格中的被访问情况。
而回溯的思路是:除了主函数以外,还需一递归函数(取名为DFS),递归函数在通过4个坐标获知移动的方向,若符合移动的条件,递归调用DFS进行网格内移动,若当前字符与字符串当前索引的字符相等,设置该网格已访问并递增索引,然后继续移动......递归往上返回的条件是索引与字符串长度相等(返回T),或者当前字符与字符串当前索引字符不想等(返回F),或者相等,但邻近所有字符与字符串下一索引字符不相等(返回F)。
1 class Solution { 2 public: 3 int dir[4][4] = { { -1,0 },{ 1,0 },{ 0,1 },{ 0,-1 } }; //4个方向坐标,分别代表往左、右、上、下移动一格 4 bool DFS(vector<vector<char>>& board, int index, int x, int y, vector<vector<bool>>& visited, string& word) 5 { 6 //移动后当前网格字符与字符串当前索引字符比较 7 if (board[x][y] == word[index] && index<word.length()) 8 { 9 //相等,索引递增,该格设为已访问 10 index++; 11 visited[x][y] = true; 12 } 13 else 14 { //否则,返回false,回退至上一DFS 15 return false; 16 } 17 //索引与字符串长度相等,说明该单词存在于网格中,结束递归,返回true 18 if (index == word.length()) return true; 19 20 //4个移动方向都进行尝试 21 for (int i = 0; i<4; i++) 22 { 23 x += dir[i][0]; 24 y += dir[i][1]; 25 26 //若该方向不越界,往其前进一格,并递归调用DFS 27 if (x >= 0 && x<board.size() && y >= 0 && y<board[0].size() && !visited[x][y]) 28 if (DFS(board, index, x, y, visited, word)) //若T,说明递归结束,继续往上返回T 29 return true; 30 31 //若进行到此,说明该方向越界或者字符不匹配,返回到原来的位置上。 32 x -= dir[i][0]; 33 y -= dir[i][1]; 34 } 35 //若进行到此,说明当前网格字符的所有邻近字符都与字符串当前索引字符不匹配,说明此路不通,撤销该网格已访问的记录,并继续往上返回F 36 visited[x][y] = false; 37 return false; 38 } 39 40 //主函数 41 bool exist(vector<vector<char>>& board, string word) { 42 int row = board.size(); 43 int col = board[0].size(); 44 vector<vector<bool>>visited(row, vector<bool>(col, false)); //二维访问数组 45 46 //遍历网格,寻找一个合适的开始位置,即该网格中与字符串第一个字符相等的那一格 47 for (int i = 0; i < row; i++) 48 for (int j = 0; j < col; j++) 49 if (DFS(board, 0, i, j, visited, word)) 50 return true; 51 return false; 52 } 53 };