leetcode里和graph相关的题目根据解题思路可以分成以下几个大类:
- Depth First Search
典型题型:求具体路径
有一类题型很常见也很重要:给你一张图,一个起始点(起始状态),一个终止状态(终止状态)让你求路径的,最典型的是走迷宫的问题。(这是我目前比较薄弱的一块) - Breadth First Search
典型题型:求最短距离
这两天做了两道求全局最短距离的题目(边的权重均为1),同样用bfs,但由于要访问每一个节点,可能需要走走回头路。这个时候visited数组就不再是记录每个点的访问情况了,而要记录的是一种状态:目前所处的位置+所有节点的访问情况,也就是说每种状态只能出现一次。
以864、Shortest Path to Get All Keys为例,visited数组存放的是(x, y, status),x、y分别是目前所处位置的横纵坐标,status记录的是每把钥匙获取的情况(用二进制数来处理)。 - Topological Sort
典型题型:node之间有先后顺序,需要判断图中是否存在有向环 - Union Find
典型题型:节点之间相互连接,求group的个数等等
有些题目的关键是如何建图,两种建图形式:
- 邻接矩阵:
例:int[][] graph = new intn; - 邻接列表:
例:List<int[]>[] graph = new List[n];
HashMap<Integer, HashMap<Integer, Integer>> graph = new HashMap<>();
图的题目给我们的常常是这三种形式:
- 二维数组,每个格子就是每个node,这种情况就不需要我们建图了,每个格子周围的四个方向就是它的连接点(在没有其他限制的条件下)
- 给出边的形式(u,v,w):这是一条两端点为u、v权重为w的边。我们需要把所有给出的边建立graph,用邻接矩阵或是邻接列表都可以。另外注意一下是directed的还是undirected的
- 给出一个二维数组,例如[[1,2],[0,1],[2]],ai表示和i和j相连,也就是a[i]存储是i点的连接点,这种情况下一般我们也不需要建图
求最短路径:
- Dijkstra
Dijkstra的两种写法:
以leetcode 743为例:
一、把除了起始点以外的其他点到起始点的距离设为0,也是最常规的写法。
class Solution {
public int networkDelayTime(int[][] times, int N, int K) {
List<int[]>[] graph = new List[N+1];
for (int i = 1; i <= N; i ++)
graph[i] = new ArrayList<>();
for (int[] time : times)
graph[time[0]].add(new int[] {time[1], time[2]});
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b)->Integer.compare(a[1], b[1]));
int[] dist = new int[N+1];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[K] = 0;
pq.offer(new int[] {K, 0});
int max = 0;
while (!pq.isEmpty()) {
int[] node = pq.poll();
int u = node[0];
max = Math.max(max, dist[u]);
for (int[] edge : graph[u]) {
int v = edge[0];
int d = edge[1];
if (dist[u]+d < dist[v]) {
dist[v] = dist[u]+d;
pq.offer(new int[] {v, dist[v]});
}
}
}
for (int i = 1; i <= N; i ++)
if (dist[i] == Integer.MAX_VALUE)
return -1;
return max;
}
}
二、不需要初始化为INF
class Solution {
public int networkDelayTime(int[][] times, int N, int K) {
boolean[] used = new boolean[N+1];
int[][] graph = new int[N+1][N+1];
for (int i = 1; i <= N; i ++) {
for (int j = 1; j <= N; j ++)
graph[i][j] = -1;
}
for (int[] time : times)
graph[time[0]][time[1]] = time[2];
PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->Integer.compare(a[1], b[1]));
pq.offer(new int[] {K, 0});
int max = 0;
while (!pq.isEmpty()) {
int[] edge = pq.poll();
int u = edge[0];
int d = edge[1];
if (used[u]) continue;
used[u] = true;
max = Math.max(max, d);
for (int i = 1; i <= N; i ++) {
if (graph[u][i] == -1) continue;
pq.offer(new int[] {i,d+graph[u][i]});
}
}
for (int i = 1; i <= N; i ++)
if (!used[i]) return -1;
return max;
}
}
- Bellman-Ford:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。