java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 |
---|
回溯+深度优先遍历
解题思路:时间复杂度O(
m
∗
n
+
s
∗
n
u
m
m*n + s*num
m∗n+s∗num),m*n是将整个board数组遍历了一遍,s是字符串word的长度,num是word这个字符串的第一个字符在board出现了几次。空间复杂度O(
m
∗
n
∗
2
m*n*2
m∗n∗2) |
---|
- 先创建一个hash表,key保存board中出现的字符,value保存对应字符的所有坐标,所需时间复杂度O(
m
∗
n
m*n
m∗n),空间复杂度O(
m
∗
n
m*n
m∗n)
- 然后查看hash表,是否缺少word中的字符,因为缺少哪怕一个字符,都无法完成word的搜索,直接返回false即可。时间复杂度可以忽略不计
- 从hash表获取word第一个字符的所有下标p,并遍历,所需时间复杂度为O(num),num为word中第一个字符在board的所有下标个数
每次遍历都需要visited数组标识我们本次路径上访问的位置,因为同一个位置不能访问多次,空间复杂度O(
m
∗
n
m*n
m∗n)
- 以每个p为起点进行深度优先遍历(从上下左右四个方向依次比对),如果当前路径没有访问这个结点,并且成功和word中当前字符对应,就继续遍历。当整个word字符串都成功比对,就返回true。
- 如果当前字符没有成功比对,就将当前位置的visited设置回false表示这个位置下次可以继续访问。然后回溯到上一步继续深度优先遍历
class Solution {
char[][] board;
String word;
int [][] directions = new int[][]{{-1,0},{0,-1},{1,0},{0,1}};
public boolean exist(char[][] board, String word) {
this.board = board;
this.word = word;
int row = board.length;
int col = board[0].length;
Map<Character, List<int[]>> dict = new HashMap<>();
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
List<int[]> val = dict.getOrDefault(board[r][c], new ArrayList<>());
val.add(new int[]{r, c});
dict.put(board[r][c], val);
}
}
for (char ch : word.toCharArray()) {
if (!dict.containsKey(ch)) return false;
}
for (int[] p : dict.get(word.charAt(0))) {
boolean ret = dfs(p[0], p[1], new boolean[row][col], 0);
if (ret) return true;
}
return false;
}
private boolean dfs(int r, int c, boolean[][] path, int index) {
int row = board.length;
int col = board[0].length;
if (index >= word.length()) return true;
if (r < 0 || r >= row || c < 0 || c >= col || path[r][c]) return false;
char ch = word.charAt(index);
if (board[r][c] != ch) return false;
path[r][c] = true;
boolean ret = false;
for(int[] direction: directions){
int nextR = r+direction[0];
int nextC = c+direction[1];
ret = dfs(nextR,nextC,path,index+1);
if(ret) return true;
}
path[r][c] = false;
return false;
}
}