「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战」。
题目:给定一个二维字符数组board,和一个字符串word,要求确定是否存在连续的word在board中,如果存在则返回true,否则false。注意:同一个单元格中的字母不允许被重复使用。
解题思路
同一个单元格内容不能重复使用,回想之前全排列也要求不能重复,当时使用了一个数组来标记已使用的元素,此时也可以考虑设置一个标记数组来标记二位字符数组中元素,每次查询时候都检查是否被使用过即可。
要确定单词是否存在在二维字符数组中,可以从上到下遍历二维字符数组,首先找到单词的第一个元素在二维数组中的位置,将该字符标记为已使用,之后检查该字符上下左右的元素是否和单词的之后元素匹配,依次递归即可确定,递归之后需要将该字符重新标记为未使用。代码如下:
public boolean exist(char[][] board, String word) {
int row = board.length;
int column=board[0].length;
int[][] visited = new int[row][column];
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(board[i][j]==word.charAt(0)){
if(dfs(board, i, j, word, visited, 0)){
return true;
}
}
}
}
return false;
}
public boolean dfs(char[][] board, int i, int j, String word, int[][] visited, int k){
if(k == word.length()){
return true;
}
if(i<0||j<0||i>=board.length||j>=board[0].length){
return false;
}
if(word.charAt(k)!=board[i][j]||visited[i][j]==1){
return false;
}
visited[i][j] = 1;
boolean res = dfs(board, i-1, j, word, visited, k+1)||dfs(board, i+1, j, word, visited, k+1)
|| dfs(board, i, j-1, word, visited, k+1) || dfs(board, i, j+1, word, visited, k+1);
visited[i][j] = 0;
return res;
}
上述代码耗时90ms,并且使用了一个额外的标记数组来标记字符数组的元素,实际上本题可以通过另一种方式来解决不重复使用的问题,只需要将已经访问的字符修改为字符数组不可能存在的字符,之后递归完成修改为原来字符即可,代码修改如下:
public boolean dfs2(char[][] board, int i, int j, String word, int k){
if(k == word.length()){
return true;
}
if(i<0||j<0||i>=board.length||j>=board[0].length){
return false;
}
if(word.charAt(k)!=board[i][j]){
return false;
}
char c = board[i][j];
board[i][j] = '#';
boolean res = dfs2(board, i-1, j, word, k+1)||dfs2(board, i+1, j, word, k+1)
|| dfs2(board, i, j-1, word, k+1) || dfs2(board, i, j+1, word, k+1);
board[i][j] = c;
return res;
}
此处选择的是将字符修改为#。最终运行耗时84ms。