“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情”
矩阵中的路径
内容
思路
这道题若要使用深度优先搜索方法解决,就先要把路径的选择看作一棵不规则的n叉树()
举个例子,若A为起点,则第一步可以走的节点为B和S,也就是说以A为根节点的求解树中,第二层的节点是B和S,以此类推下去,我们可以得到一棵完整的求解树,那么若再以board的其他字符作为起点,我们最后可以得到一片求解森林,我们要做的,就是在这片求解森林中用深度优先方法遍历求解树,然后找到与word相同的解的路径。
由于单纯的dfs方式会出现超时情况,所以我们还需要加入剪枝步骤,主要需要剪掉以下枝节:
- 访问到以前走过的节点
- 访问到字符不符合word对应位置的节点
这样出来的求解树更加简洁,搜索效率更高
代码实现
class Solution {
public boolean exist(char[][] board, String word) {
int x=board.length;
int y=board[0].length;
char[] words=word.toCharArray();
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
if(dfs(board,i,j,words,0))return true;
}
}
return false;
}
public boolean dfs( char[][] board, int x, int y, char[] word, int label) {
if (y >= board[0].length || x >= board.length || y < 0 || x < 0|| board[x][y] != word[label] )
return false;
if (label == word.length-1) return true;
//将board对应位置设为\0,在再结合上面的判断条件,就不会出现访问到之前访问过的节点的情况了
board[x][y]='\0';
//这里使用短路与是因为正常分开4个dfs方法还是会出现超时情况,也可以用4个数组分别记下上下左右4个方向对应的坐标变化,用for循环遍历
boolean flag=dfs( board, x, y + 1, word, label + 1) || dfs( board, x, y - 1, word, label + 1) || dfs( board, x + 1, y, word, label + 1)|| dfs(board, x - 1, y, word, label + 1);
//注意遍历完之后一定要把赋值还原,不然会出bug
board[x][y]=word[label];
return flag;
}
}
机器人的运动范围
内容
思路
同样是在矩阵中遍历,但与上一题的区别是这一题所需要找的东西不同,上一题只需要遍历到一条路径返回一个布尔类型的值就可以了,但是这里要求有步数的限制,以及需要把访问到的节点都记录下来(计数就行),同样的地方是不能访问已经访问过的节点。
代码实现
class Solution {
public int cnt=0;
public int max=0;
public int movingCount(int m, int n, int k) {
boolean[][] x=new boolean[m][n];
max=k;
bfs(x,0,0);
return cnt;
}
//求数位和
public int digitSum(int x){
int ans=0;
while(x>0){
ans+=x%10;
x/=10;
}
return ans;
}
//深度优先搜索
public void bfs(boolean[][] b,int x,int y){
//判断有没有出界或者到达次数限制
if(x<0||y<0||x>b.length-1||y>b[0].length-1||b[x][y]||digitSum(x)+digitSum(y)>max) return;
b[x][y]=true;
cnt++;
//四个方向都走一下
bfs(b,x+1,y);
bfs(b,x-1,y);
bfs(b,x,y+1);
bfs(b,x,y-1);
}
}