图的遍历相对于树的的遍历更加复杂,图中的遍历问题大多是有多个原点的,而数的遍历我们只需要从根节点出发即可,其次,树是具有方向性的。而图的遍历中,倘若是无向图则不具有方向性。我们在遍历的同时必须对原数据加以处理,防止重复遍历。
图的深度优先遍历(DFS)
class Solution {
public int movingCount(int key, int rows, int cols)
{
Boolean[][] visited=new Boolean[rows][cols];
for(int i=0;i<visited.length;i++){
for(int j=0;j<visited[i].length;j++){
visited[i][j]=false;
}
}
return DFS(0,0,visited,rows,cols,key);
}
public int DFS(int i,int j,Boolean[][] visited,int r,int c,int key){
if(i==r||j==c||visited[i][j]){
return 0;
}
visited[i][j]=true;
if(count(i)+count(j)>key){
return 0;
}
return DFS(i+1,j,visited,r,c,key)+DFS(i,j+1,visited,r,c,key)+1;
}
public int count(int n){
int sum=0;
while(n>0){
sum+=n%10;
n/=10;
}
return sum;
}
}
class Solution {
public int maxAreaOfIsland(int[][] grid) {
int max=0;
int rows=grid.length;
int cols=grid[0].length;
Boolean visited[][]=new Boolean[rows][cols];
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(grid[i][j]==1)
max=Math.max(DFS(i,j,grid),max);//max存放上一个岛屿的面积
}
}
return max;
}
public int DFS(int x,int y,int[][] grid){
if(x<0 || y<0 || x>=grid.length || y>=grid[0].length||grid[x][y]==0){
return 0;
}
grid[x][y]=0;//将访问后的点的值设为0 防止重复访问
int count=1;
count+=DFS(x+1,y,grid);
count+=DFS(x-1,y,grid);
count+=DFS(x,y+1,grid);
count+=DFS(x,y-1,grid);
return count;
}
}
这两道题都是关于图的遍历问题,所以我们可以使用BFS或者DFS两种方法。不同点在于第一个问题我们是单起点的从一个点遍历图得到答案。而第二个问题中 我是对图的遍历是多起点的(不同的岛屿因不相接而导致面积不同)。我们可以想象成这是一个非连通图,每一个由一组成的岛屿是一个连通分量,通过for循环不断更换节点最终达到访问全部图的目的。
在图的遍历中,为了防止重复检测某一个结点我们常需要对它进行标记。上面两个题中的标记。都修改了原始数据,假若我们需要重多个起点遍历图的原始数据,这样显然是不行的。我们可以根据深度优先遍历 递归的特点,并且搭配移动数组[dx[]=0,0,-1,1],dy[]=[-1,1,0,0]。在每一次遍历这个点的上下左右时储存这个点的值然后,再最后将其复原。
char temp= board[i][j];
board[i][j]='0';
for(int l=0;l<4;l++){
int newx=i+dx[l];
int newy=j+dy[l];
if(newx>=0 && newx<board.length && newy>=0 ){
if(board[newx][newy]!='0'){
flag=DFS(newx,newy,board,word,len+1);
}
}
}
board[i][j]=temp;
这样每当我们以一个新的起点遍历图时,所有的数据都没有被修改过。
图的广度优先遍历(BFS)
class Solution {
public int[][] updateMatrix(int[][] mat) {
Queue<int[]> queue=new LinkedList<>();
for(int i=0;i<mat.length;i++){
for(int j=0;j<mat[0].length;j++){
if(mat[i][j]==0){
queue.offer(new int[]{i,j});//队列存放的i,j数组相当于一个坐标。
}
else{
mat[i][j]=-1;
}
}
}
int dx[]=new int[]{-1,1,0,0};
int dy[]=new int[]{0,0,-1,1};//遍历图时所使用的方向矩阵。
while(!queue.isEmpty()){
int[] p=queue.poll();
int x=p[0];
int y=p[1];
for(int i=0;i<4;i++){
int newx=x+dx[i];
int newy=y+dy[i];
if(newx>=0 &&newx<mat.length &&newy>=0&&newy<mat[0].length&&mat[newx][newy]==-1){
mat[newx][newy]=mat[x][y]+1;
queue.offer(new int[]{newx,newy});
}
}
}
return mat;
}
}
学习如何利用BFS的方法遍历矩阵,以及原地修改矩阵的值的方法。