1、问题描述
Given a 2D board and a word, find if the word exists in the grid.
The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.
For example,
Given board =
[ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ]
word = "ABCCED"
, -> returns true
,
word = "SEE"
, -> returns true
,
word = "ABCB"
, -> returns false
.
2、边界条件:无
3、思路:先轮询board的每一个点,作为起点。走到某个点,首先检查是否到base case,即字符串最后+1,然后检查该点的边界和visited,再检查是否为匹配字符,通过则标记为visited,继续向四周查找。以此点为起点继续向四周查找下一个匹配字符,直到找完,递归生成。base case:找完整个字符串。index == word.length()
4、代码实现:
错误示例
class Solution { public boolean exist(char[][] board, String word) { int[][] visited = new int[board.length][board[0].length]; for (int i = 0; i < visited.length; i++) { for (int j = 0; j < visited[0].length; j++) { visited[i][j] = 0; } } return existString(board, visited, word, 0, 0, 0); } public boolean existString(char[][] board, int[][] visited, String word, int index, int posX, int posY) { if (index == word.length()) { return true; } if(posX < 0 || posX >= board.length || posY < 0 || posY >= board[0].length) { return false; } if (visited[posX][posY] == 1) { return false; } if (index == 0) { //index=0与其他情况还是有区别的,本来就是在寻找递归的起点,所以放在主函数里面。 for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if(board[i][j] == word.charAt(index)) { //不需要这里判断,只要轮询每个点,作为起点就可以了。 posX = i; posY = j; visited[posX][posY] = 1; if (true == existString(board, visited, word, index + 1, posX, posY)) { return true; } visited[i][j] = 0; } } } } else { if (board[posX][posY] != word.charAt(index)) { return false; } if (posX + 1 >= 0 && posX + 1 < board.length && 1 != visited[posX + 1][posY] && board[posX + 1][posY] == word.charAt(index + 1)) { visited[posX + 1][posY] = 1; //还未检查这一点,就设置为visited,在visited检查时肯定false if (true == existString(board, visited, word, index + 1, posX + 1, posY)) { return true; } visited[posX + 1][posY] = 0; } if (posX - 1 >= 0 && posX - 1 < board.length && 1 != visited[posX - 1][posY] && board[posX - 1][posY] == word.charAt(index + 1)) { visited[posX - 1][posY] = 1; if (true == existString(board, visited, word, index + 1, posX - 1, posY)) { return true; } visited[posX - 1][posY] = 0; } if (posY + 1 >= 0 && posY + 1 < board[].length && 1 != visited[posX][posY + 1] && board[posX][posY + 1] == word.charAt(index + 1)) { visited[posX][posY + 1] = 1; if (true == existString(board, visited, word, index + 1, posX, posY + 1)) { return true; } visited[posX][posY + 1] = 0; } if (posY - 1 >= 0 && posY - 1 < board[0].length && 1 != visited[posX][posY - 1] && board[posX][posY - 1] == word.charAt(index + 1)) { visited[posX][posY - 1] = 1; if (true == existString(board, visited, word, index + 1, posX, posY - 1)) { return true; } visited[posX][posY - 1] = 0; } } return false; } }
修改后示例:
思路是走到某个点,首先检查是否到base case,即字符串最后+1,然后检查该点的边界和visited,再检查是否为匹配字符,通过则标记为visited,继续向四周查找。
class Solution { public boolean exist(char[][] board, String word) { int[][] visited = new int[board.length][board[0].length]; for (int i = 0; i < visited.length; i++) { //初始化visited for (int j = 0; j < visited[0].length; j++) { visited[i][j] = 0; } } int index = 0; for (int posX = 0; posX < board.length; posX++) { for (int posY = 0; posY < board[0].length; posY++) {//轮询每个点,然后以此点为起点开始查找 if (true == existString(board, visited, word, index, posX, posY)) {//index始终为0 return true; } } } return false; } public boolean existString(char[][] board, int[][] visited, String word, int index, int posX, int posY) { if (index == word.length()) { //base case return true; } if(posX < 0 || posX >= board.length || posY < 0 || posY >= board[0].length) {//检查边界 return false; } if (visited[posX][posY] == 1) {//检查是否visited return false; } if (board[posX][posY] != word.charAt(index)) {//检查字符是否匹配 return false; } visited[posX][posY] = 1;//以上通过则标记为visited,然后向四周轮询 if (true == existString(board, visited, word, index + 1, posX + 1, posY)) { return true; } if (true == existString(board, visited, word, index + 1, posX - 1, posY)) { return true; } if (true == existString(board, visited, word, index + 1, posX, posY + 1)) { return true; } if (true == existString(board, visited, word, index + 1, posX, posY - 1)) { return true; } visited[posX][posY] = 0;//恢复现场 return false; } }
进一步简化:
class Solution { public boolean exist(char[][] board, String word) { int[][] visited = new int[board.length][board[0].length]; for (int i = 0; i < visited.length; i++) { for (int j = 0; j < visited[0].length; j++) { visited[i][j] = 0; } } int index = 0; for (int posX = 0; posX < board.length; posX++) { for (int posY = 0; posY < board[0].length; posY++) { if (existString(board, visited, word, index, posX, posY)) { return true; } } } return false; } public boolean existString(char[][] board, int[][] visited, String word, int index, int posX, int posY) { if (index == word.length()) { return true; } if(posX < 0 || posX >= board.length || posY < 0 || posY >= board[0].length) { return false; } if (visited[posX][posY] == 1) { return false; } if (board[posX][posY] != word.charAt(index)) { return false; } visited[posX][posY] = 1; if (existString(board, visited, word, index + 1, posX + 1, posY) || existString(board, visited, word, index + 1, posX - 1, posY) || existString(board, visited, word, index + 1, posX, posY + 1) || existString(board, visited, word, index + 1, posX, posY - 1)) { return true; } visited[posX][posY] = 0; return false; } }