BFS解决问题的算法流程,伪代码实现:
/**
* Return the length of the shortest path between root and target node.
*/
int BFS(Node root, Node target) {
Queue<Node> queue; // store all nodes which are waiting to be processed
Set<Node> visited; // store all the nodes that we've visited
int step = 0; // number of steps neeeded from root to current node
// initialize
add root to queue;
add root to visited;
// BFS
while (queue is not empty) {
step = step + 1;
// iterate the nodes which are already in the queue
int size = queue.size();
for (int i = 0; i < size; ++i) {
Node cur = the first node in queue;
return step if cur is target;
for (Node next : the neighbors of cur) {
if (next is not in visited) {
add next to queue;
add next to visited;
}
}
remove the first node from queue;
}
}
return -1; // there is no path from root to target
}
1、迷宫遍历问题
Walls and Gates (LeetCode) (墙和门问题)
下面这两个是一类型题,既可以BFS也可以DFS
第二类型:图的遍历问题
图中某个node到达的最短距离和最短路径
这是一道求深度的题,和二叉树求深度或者某个节点距根节点最短距离是一回事
Open the Lock (密码锁解锁问题)
图中某个node的可达性
Keys and Rooms (LeetCode)(钥匙和门问题)
基本步骤:
(1)根据实际解决的问题,把起点"位置信息"(在矩阵中,就是行和列,可以是自己本身,其目的是根据这个信息能找到neighbers)放到Queue中。比如在Walls and Gates问题中,是首先把所有的gate位置信息放到queue中。在Number of Islands问题中,是先把1位置信息放到queue中,一次BFS(queue为空)结束后,还能找到1的话,再放到queue中。
(2)开始BFS,直到queue为空。这步最重要的是找到neighbors,这个找neighbors就有难度了,这个需要大量的练习和总结。如果是矩阵的话,很好说,上下左右。遍历的过程中,关键的一步是,需要标注出遍历过的node,这个也是根据具体问题实现的,有时需要set的辅助实现,有时在内部结构中就能实现。比如:在Walls and Gates问题中,-1墙(障碍物)是不需要访问的,访问过的点都是更新成到gate的距离,所以,障碍物和访问过的node跳过,只有empty才能访问并入对。在Number of Islands问题中,0水(障碍物)不需要访问,访问过的1都变成0,所以只有1才是需要访问的并入队。
进一步说明一下:
Walls and Gates 和Number of Islands问题,在BFS过程中,是一个元素一个元素进行处理的。而Open the Lock问题,在BFS过程中,是一层一层进行处理的,是有层的概念的,而且解决问题是需要这个层概念的,这种问题一般是寻找路径问题。其实Open the Lock也是寻找最短路径问题,和二叉树中寻找最短路径是一样的,只不过复杂了点。在二叉树中,是单方向的,能很简单的找到子节点,open the lock 其实是图,图中寻找neighbor节点比较麻烦,而是不是单方向的。