题目地址:
https://www.lintcode.com/problem/shortest-path-in-undirected-graph/description
给定一个无向图,边权都为 1 1 1,再给定两个图中的节点,问这两个节点之间的最短路距离。
思路是双向BFS。用两个队列分别记录两端BFS的每一层遍历的节点,再用两个哈希表记录两端BFS访问过的节点,直到两边遍历的节点碰到为止,返回所需步数即可。代码如下:
import java.util.*;
public class Solution {
/**
* @param graph: a list of Undirected graph node
* @param A: nodeA
* @param B: nodeB
* @return: the length of the shortest path
*/
public int shortestPath(List<UndirectedGraphNode> graph, UndirectedGraphNode A, UndirectedGraphNode B) {
// Write your code here
// 如果两个顶点相同,则不需走任何步数,返回0
if (A == B) {
return 0;
}
Queue<UndirectedGraphNode> beginQueue = new LinkedList<>(), endQueue = new LinkedList<>();
Set<UndirectedGraphNode> beginSet = new HashSet<>(), endSet = new HashSet<>();
beginQueue.offer(A);
beginSet.add(A);
endQueue.offer(B);
endSet.add(B);
int res = 0;
while (!beginQueue.isEmpty() && !endQueue.isEmpty()) {
int beginSize = beginQueue.size(), endSize = endQueue.size();
res++;
for (int i = 0; i < beginSize; i++) {
UndirectedGraphNode cur = beginQueue.poll();
for (UndirectedGraphNode neighbor : cur.neighbors) {
if (endSet.contains(neighbor)) {
return res;
}
if (beginSet.add(neighbor)) {
beginQueue.offer(neighbor);
}
}
}
res++;
for (int i = 0; i < endSize; i++) {
UndirectedGraphNode cur = endQueue.poll();
for (UndirectedGraphNode neighbor : cur.neighbors) {
if (beginSet.contains(neighbor)) {
return res;
}
if (endSet.add(neighbor)) {
endQueue.offer(neighbor);
}
}
}
}
// 如果某个队列为空,说明已经走到了边界并且无法继续扩展,
// 但仍未与另一端遍历的顶点“接壤”,说明两个点不连通,返回正无穷
return Integer.MAX_VALUE;
}
}
class UndirectedGraphNode {
int label;
List<UndirectedGraphNode> neighbors;
UndirectedGraphNode(int x) {
label = x;
neighbors = new ArrayList<>();
}
}
时空复杂度 O ( V + E ) O(V+E) O(V+E)。