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:
相關文章
相關標籤/搜索