Leetcode笔记之Graph

leetcode里和graph相关的题目根据解题思路能够分红如下几个大类:node

  1. Depth First Search
    典型题型:求具体路径
    有一类题型很常见也很重要:给你一张图,一个起始点(起始状态),一个终止状态(终止状态)让你求路径的,最典型的是走迷宫的问题。(这是我目前比较薄弱的一块)
  2. Breadth First Search
    典型题型:求最短距离
    这两天作了两道求全局最短距离的题目(边的权重均为1),一样用bfs,但因为要访问每个节点,可能须要走走回头路。这个时候visited数组就再也不是记录每一个点的访问状况了,而要记录的是一种状态:目前所处的位置+全部节点的访问状况,也就是说每种状态只能出现一次。
    以86四、Shortest Path to Get All Keys为例,visited数组存放的是(x, y, status),x、y分别是目前所处位置的横纵坐标,status记录的是每把钥匙获取的状况(用二进制数来处理)。
  3. Topological Sort
    典型题型:node之间有前后顺序,须要判断图中是否存在有向环
  4. Union Find
    典型题型:节点之间相互链接,求group的个数等等

有些题目的关键是如何建图,两种建图形式:数组

  1. 邻接矩阵:
    例:int[][] graph = new intn;
  2. 邻接列表:
    例:List<int[]>[] graph = new List[n];
    HashMap<Integer, HashMap<Integer, Integer>> graph = new HashMap<>();

图的题目给咱们的经常是这三种形式:code

  1. 二维数组,每一个格子就是每一个node,这种状况就不须要咱们建图了,每一个格子周围的四个方向就是它的链接点(在没有其余限制的条件下)
  2. 给出边的形式(u,v,w):这是一条两端点为u、v权重为w的边。咱们须要把全部给出的边创建graph,用邻接矩阵或是邻接列表均可以。另外注意一下是directed的仍是undirected的
  3. 给出一个二维数组,例如[[1,2],[0,1],[2]],ai表示和i和j相连,也就是a[i]存储是i点的链接点,这种状况下通常咱们也不须要建图

求最短路径:leetcode

  1. Dijkstra
    Dijkstra的两种写法:
    以leetcode 743为例:
    1、把除了起始点之外的其余点到起始点的距离设为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;
    }
}
2、不须要初始化为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;
    }
}
  1. Bellman-Ford:
相关文章
相关标签/搜索