300分钟-深度与广度优先搜索

深度优先搜索算法(DFS)

DFS解决的问题
连通性的问题,即给定一个起始点(或某种起始状态)和一个终点(或某种最终状态),判断是否有一条路径能从起点连接到终点
很多情况下连通的路径有多条,只需要找出一条即可,DFS只关心路径存在与否,不关心长短。

算法思想
从起点出发,选择一个可选方向不断向前,直到无法继续。然后尝试另一种方向,直到最后找到终点。
入栈(或出栈)-找栈顶节点的 邻接顶点(找不到就出栈)-入栈

一个走迷宫的实例:
在这里插入图片描述

用非递归的DFS可以提高效率

bool dfs(vector <vector<int>> maze,int x,int y){
    stack<vector<int>> sta;
    sta.push({x,y});//将起始点压栈
    maze[x][y]=-1;//将起始点标为已访问

    while(!sta.Empty()){//栈不为空就一直循环
        vector<int> pos=stack.pop();//从栈顶取出要处理的点
        x=pos[0];y=pos[1];

        if(x==B[0]&&y=B(1)){//到达目的地返回true
            return true;
        }

        for(int d=0;d<4;d++){//没到的话从四个方向尝试
            int i=x+dx[d],j=y+dy[d];
            if(isSafe(maze,i,j)){//判断有没有撞墙
                sta.push({i,j});
                maze[i][j]=-1;//标记已访问
            }
           
        }
    }
    return false;//尝试所有可能都没找到b,返回
}

DFS复杂度分析
图有两种表示方式:

  • 邻接表(图里有V个顶点,E条边)
    访问所有顶点的时间为O(V) 查找所有顶点邻居的时间O(E) 时间复杂度O(V+E)

  • 邻接矩阵
    查找每个顶点的邻居需要O(V)时间,所以查找整个矩阵需要O(V^2)时间。

找迷宫最短路径
一边寻找目的地,一边记录它和起始点的距离
当发现从某个方向过来所需要的步数更少,则更新到这个点的步数,如果发现步数更多,则不再继续尝试

情况一:从某方向到达该点所需要的步数更少则更新
在这里插入图片描述

情况二:从各个方向到达该点所需要的步数都更多则不再尝试
在这里插入图片描述

在这里插入图片描述

广度优先搜索(BFS)

  • 一般用于解决最短路径问题
  • 从起始点出发,一层层地进行
  • 每层中的点距离起点步数是相同的

广度优先其实就是把起点放入队列,然后不断取出,找邻点,处理,再放入队列。看一个例题:
在这里插入图片描述

class Solution {
public:
	vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
		queue <vector<int>> q;
		int m = matrix.size(), n = matrix[0].size();
		//遍历所有节点 将0入队作为搜索起点,1置为-1表示未访问
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				if (matrix[i][j] == 0) q.push({ i,j });
				else matrix[i][j] = -1;
			}
		}

		//这里定义x是行 y是列的含义
		vector<int> dx = {0,0,1,-1};
		vector<int> dy = { 1,-1,0,0 };
		while (!q.empty()) {
			vector<int> cur = q.front();
			q.pop();
			int x=cur[0], y = cur[1];
			for (int i = 0; i < 4; i++) {
				int newX = x + dx[i];
				int newY = y + dy[i];

				//在范围内且是没访问过的1
				if (newX < m && newY < n && newY>=0 &&newX>=0 && matrix[newX][newY] == -1) {
					matrix[newX][newY] = matrix[x][y] + 1;
					q.push({ newX,newY });//访问过的节点入队
				}
			}
		}

		return matrix;
	}
};

双端BFS
同时从起始点和终点开始进行的广度优先搜索为双端BFS。

借助数据结构:队列。每次将一个点的所有相邻节点入队,打印输出后从队列取出下一节点。
在这里插入图片描述
复杂度分析:

  • 邻接表:O(V+E)
  • 邻接矩阵:O(V^2)
    迷宫寻路:
    时间:O(MN)
    空间:O(M
    N)

猜你喜欢

转载自blog.csdn.net/weixin_42189888/article/details/105196521
今日推荐