• [LeetCode] 1129. Shortest Path with Alternating Colors


    Consider a directed graph, with nodes labelled 0, 1, ..., n-1.  In this graph, each edge is either red or blue, and there could be self-edges or parallel edges.

    Each [i, j] in red_edges denotes a red directed edge from node i to node j.  Similarly, each [i, j] in blue_edges denotes a blue directed edge from node i to node j.

    Return an array answer of length n, where each answer[X] is the length of the shortest path from node 0 to node X such that the edge colors alternate along the path (or -1 if such a path doesn't exist).

    Example 1:

    Input: n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
    Output: [0,1,-1]
    

    Example 2:

    Input: n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
    Output: [0,1,-1]
    

    Example 3:

    Input: n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
    Output: [0,-1,-1]
    

    Example 4:

    Input: n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
    Output: [0,1,2]
    

    Example 5:

    Input: n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]]
    Output: [0,1,1]

    Constraints:

    • 1 <= n <= 100
    • red_edges.length <= 400
    • blue_edges.length <= 400
    • red_edges[i].length == blue_edges[i].length == 2
    • 0 <= red_edges[i][j], blue_edges[i][j] < n

    颜色交替的最短路径。

    在一个有向图中,节点分别标记为 0, 1, ..., n-1。这个图中的每条边不是红色就是蓝色,且存在自环或平行边。

    red_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的红色有向边。类似地,blue_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的蓝色有向边。

    返回长度为 n 的数组 answer,其中 answer[X] 是从节点 0 到节点 X 的红色边和蓝色边交替出现的最短路径的长度。如果不存在这样的路径,那么 answer[x] = -1。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/shortest-path-with-alternating-colors
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    这是一道图论的题。题目说了是一个有向图并且找的是一条最短的,红蓝交替的从0去到其他所有节点的路径,那么思路应该是BFS。既然是图的题,那么我们一开始要做的依然是把图创建起来。这道题比较特殊的地方在于因为有可能两个node之间既有红色边又有蓝色边,所以我们这里选择创建的是邻接矩阵,矩阵里面如果放的是 -n 表示两个点不相连;矩阵里面如果放的是 1 表示两个点之间有一条红色的边,-1 表示有一条蓝色的边,红蓝都有我们用0表示。

    既然是BFS,那么queue里面一开始我们放(0, 1)和(0,-1),表示去到0的点有红色和蓝色两种情况。从queue中弹出的时候,我们判断的是从0去到所有其他的点,是否存在一条有效的边同时颜色跟之前的颜色相反。同时这里我们为了防止死循环,需要用一个hashset记录遍历过的点和边的颜色(记录一下之前是通过什么颜色的边访问到某个点的)。

    时间O(V + E)

    空间O(n) - hashset

    Java实现

     1 class Solution {
     2     public int[] shortestAlternatingPaths(int n, int[][] red_edges, int[][] blue_edges) {
     3         int[][] g = new int[n][n];
     4         buildGraph(g, n, red_edges, blue_edges);
     5 
     6         Queue<int[]> queue = new LinkedList<>();
     7         // [node, color]
     8         queue.offer(new int[] { 0, 1 });
     9         queue.offer(new int[] { 0, -1 });
    10         int step = 0;
    11         int[] res = new int[n];
    12         Arrays.fill(res, Integer.MAX_VALUE);
    13         res[0] = 0;
    14 
    15         // 记录某个点是否以某种颜色的方式visited过
    16         Set<String> visited = new HashSet<>();
    17         while (!queue.isEmpty()) {
    18             int size = queue.size();
    19             step++;
    20             for (int i = 0; i < size; i++) {
    21                 int[] cur = queue.poll();
    22                 int node = cur[0];
    23                 int color = cur[1];
    24                 int oppoColor = -color;
    25 
    26                 for (int j = 1; j < n; j++) {
    27                     if (g[node][j] == oppoColor || g[node][j] == 0) {
    28                         if (!visited.add(j + "" + oppoColor)) {
    29                             continue;
    30                         }
    31                         queue.offer(new int[] { j, oppoColor });
    32                         res[j] = Math.min(res[j], step);
    33                     }
    34                 }
    35             }
    36         }
    37 
    38         for (int i = 1; i < n; i++) {
    39             if (res[i] == Integer.MAX_VALUE) {
    40                 res[i] = -1;
    41             }
    42         }
    43         return res;
    44     }
    45 
    46     private void buildGraph(int[][] g, int n, int[][] red_edges, int[][] blue_edges) {
    47         for (int i = 0; i < n; i++) {
    48             // 初始化为-n
    49             Arrays.fill(g[i], -n);
    50         }
    51 
    52         // 红色边标记成1
    53         for (int[] e : red_edges) {
    54             int from = e[0];
    55             int to = e[1];
    56             g[from][to] = 1;
    57         }
    58 
    59         for (int[] e : blue_edges) {
    60             int from = e[0];
    61             int to = e[1];
    62             // 如果有红色边了,标记成0
    63             // 如果没有红色边,标记成-1
    64             if (g[from][to] == 1) {
    65                 g[from][to] = 0;
    66             } else {
    67                 g[from][to] = -1;
    68             }
    69         }
    70     }
    71 }

    LeetCode 题目总结

  • 相关阅读:
    python3----数据结构
    Java的同步容器和并发容器
    Java基础——IO
    JVM(2)——GC算法和收集器
    Java集合(2)——深入理解ArrayList、Vector和LinkedList
    java线程(7)——阻塞队列BlockingQueue
    JVM(1)——简介
    java泛型——基本使用
    java线程(6)——线程池(下)
    java线程(5)——线程池(上)
  • 原文地址:https://www.cnblogs.com/cnoodle/p/14444814.html
Copyright © 2020-2023  润新知