zoukankan      html  css  js  c++  java
  • [Swift]LeetCode1129. 颜色交替的最短路径 | Shortest Path with Alternating Colors

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/11179555.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    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

    示例 1:

    输入:n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
    输出:[0,1,-1]
    

    示例 2:

    输入:n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
    输出:[0,1,-1]
    

    示例 3:

    输入:n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
    输出:[0,-1,-1]
    

    示例 4:

    输入:n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
    输出:[0,1,2]
    

    示例 5:

    输入:n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]]
    输出:[0,1,1]

    提示:

    • 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

    Runtime: 68 ms
    Memory Usage: 21 MB
     1 class Solution {
     2     var n:Int = 0
     3     func shortestAlternatingPaths(_ n: Int, _ red_edges: [[Int]], _ blue_edges: [[Int]]) -> [Int] {
     4         var rGraph:[[Int]] = [[Int]]()
     5         self.n = n
     6         build(&rGraph, red_edges)
     7         var bGraph:[[Int]] = [[Int]]()
     8         build(&bGraph, blue_edges)
     9         
    10         var dist:[[Int]] = [[Int]](repeating:[Int](repeating:0,count:n),count:2)
    11         for i in 0..<2
    12         {
    13             for j in 0..<n
    14             {
    15                 dist[i][j] = Int.max
    16             }
    17         }
    18         dist[0][0] = 0
    19         dist[1][0] = 0
    20         var queue:[[Int]] = [[Int]]()
    21         queue.append([0, 0])
    22         queue.append([0, 1])
    23         
    24         while(!queue.isEmpty)
    25         {
    26             var cur:[Int] = queue.removeFirst()
    27             if cur[1] == 0
    28             {
    29                 for u in rGraph[cur[0]]
    30                 {
    31                     if dist[1][u] == Int.max
    32                     {
    33                         dist[1][u] = dist[cur[1]][cur[0]] + 1
    34                         queue.append([u, 1])
    35                     }                    
    36                 }
    37             }
    38             else
    39             {
    40                 for u in bGraph[cur[0]]
    41                 {
    42                     if dist[0][u] == Int.max
    43                     {
    44                         dist[0][u] = dist[cur[1]][cur[0]] + 1
    45                         queue.append([u, 0])
    46                     }
    47                 }
    48             }            
    49         }
    50         var ans:[Int] = [Int](repeating:0,count:n)
    51         for i in 0..<n
    52         {
    53             ans[i] = min(dist[0][i], dist[1][i]);
    54             if ans[i] == Int.max
    55             {
    56                 ans[i] = -1
    57             }
    58         }
    59         return ans
    60     }
    61     
    62     func build(_ graph:inout [[Int]],_ edges:[[Int]])
    63     {
    64         graph = [[Int]](repeating:[Int](),count:n)
    65         for i in 0..<edges.count
    66         {
    67             let u:Int = edges[i][0]
    68             let v:Int = edges[i][1]
    69             graph[u].append(v)
    70         }
    71     }
    72 }

    76ms
     1 class Solution {
     2     func shortestAlternatingPaths(_ n: Int, _ red_edges: [[Int]], _ blue_edges: [[Int]]) -> [Int] {    
     3         var reds = [[Int]](repeating: [Int](), count: n)
     4         var blues = reds
     5         for e in red_edges {
     6             var arr = reds[e[0]]
     7             arr.append(e[1])
     8             reds[e[0]] = arr
     9         }
    10         for e in blue_edges {
    11             var arr = blues[e[0]]
    12             arr.append(e[1])
    13             blues[e[0]] = arr
    14         }
    15         var q = [[0, 0]]
    16         var res = [Int](repeating: -1, count: n)
    17         var moves = 0
    18         var seens = Set<String>()
    19         while !q.isEmpty {
    20             let size = q.count
    21             for _ in 0..<size {
    22                 var cur = q.removeFirst()
    23                 let key = "(cur[0])" + " " + "(cur[1])"
    24                 if seens.contains(key) {
    25                     continue
    26                 }
    27                 seens.insert(key)
    28                 if res[cur[0]] == -1 {
    29                     res[cur[0]] = moves
    30                 }
    31 
    32                 if cur[1] == 2 || cur[1] == 0 {
    33                     if reds[cur[0]].count > 0 {
    34                         for child in reds[cur[0]] {
    35                             q.append([child, 1])
    36                         }
    37                     }
    38                 }
    39 
    40                 if cur[1] == 1 || cur[1] == 0 {
    41                     if blues[cur[0]].count > 0 {
    42                         for child in blues[cur[0]] {
    43                             q.append([child, 2])
    44                         }
    45                     }
    46                 }
    47             }
    48             moves += 1
    49         }
    50         return res
    51     }
    52 }

    92ms

     1 class Solution {
     2     func shortestAlternatingPaths(_ n: Int, _ red_edges: [[Int]], _ blue_edges: [[Int]]) -> [Int] {
     3         var r_graph = [Int: [Int]]()
     4         var b_graph = [Int: [Int]]()
     5         var isVisited = Set<Int>()
     6         for edge in red_edges {
     7             r_graph[edge[0]] = r_graph[edge[0]] ?? [Int]()
     8             r_graph[edge[0]]!.append(edge[1])
     9         }
    10         
    11         for edge in blue_edges {
    12             b_graph[edge[0]] = b_graph[edge[0]] ?? [Int]()
    13             b_graph[edge[0]]!.append(edge[1])
    14         }
    15         
    16         var result = [Int](repeating: -1, count: n)
    17         var level = -1
    18         var queue = [[-1, 0]]
    19         while queue.count > 0 {
    20             let size = queue.count 
    21             level += 1
    22             var tempQueue = [[Int]]()
    23             for curr in queue {
    24                 // guard !isVisited.contains(curr[1]) else { continue }
    25                 // isVisited.insert(curr[1])
    26                 if result[curr[1]]  == -1 {
    27                     result[curr[1]] = level
    28                 } else {
    29                     result[curr[1]] = min(result[curr[1]], level)
    30                 }
    31                 
    32                 if curr[0] == -1 { 
    33                     if let red = r_graph[0] {
    34                         for node in red {
    35                             tempQueue.append([0, node])
    36                         }
    37                         r_graph.removeValue(forKey: 0)
    38                     }
    39                     
    40                     if let blue = b_graph[0] {
    41                         for node in blue {
    42                             tempQueue.append([1, node])
    43                         }
    44                         b_graph.removeValue(forKey: 0)
    45                     }
    46                     
    47                 }
    48                 // last is red
    49                 if curr[0] == 0 {
    50                     let next = curr[1]
    51                     if let blue = b_graph[next] {
    52                         for node in blue {
    53                             tempQueue.append([1, node])
    54                         }
    55                         b_graph.removeValue(forKey: next)
    56                     }
    57                 }
    58                 
    59                 if curr[0] == 1 {
    60                     let next = curr[1]
    61                     if let red = r_graph[next] {
    62                         for node in red {
    63                             tempQueue.append([0, node])
    64                         }
    65                         r_graph.removeValue(forKey: next)
    66                     }
    67                 }
    68             }
    69             queue = tempQueue
    70             // print(queue)
    71         }
    72         return result
    73     }
    74 }

    96ms

      1 class Solution {
      2     enum EdgeColor: CaseIterable {
      3         case red
      4         case blue
      5     }
      6 
      7     struct EdgeColorHelper {
      8         private init() {
      9         }
     10 
     11         static func toString(_ edgeColor: EdgeColor) -> String {
     12             switch edgeColor {
     13                 case .red:
     14                     return "R"
     15                 case .blue:
     16                     return "B"
     17             }
     18         }
     19     }
     20 
     21     struct MoveTo: Hashable, CustomDebugStringConvertible {
     22         let edgeColor: EdgeColor
     23         let from: Int
     24         let to: Int
     25 
     26         init(from: Int, to: Int, edgeColor: EdgeColor) {
     27             self.edgeColor = edgeColor
     28              self.from = from
     29             self.to = to
     30         }
     31 
     32         var debugDescription: String {
     33             return "(self.from)->(self.to):(EdgeColorHelper.toString(self.edgeColor))"
     34         }
     35     }
     36 
     37     class Reachability: CustomDebugStringConvertible {
     38         private var reached = [Int:Int]() // { from zero to { to: length } }
     39 
     40          init(edges: EdgeList) {
     41             var length = 0
     42             var visited = Set<MoveTo>()
     43             var moves: [MoveTo] = [ MoveTo(from: 0, to: 0, edgeColor: .red), MoveTo(from: 0, to: 0, edgeColor: .blue) ]
     44             while moves.count > 0 {
     45                 var nextMoves = [MoveTo]()
     46                 for mv in moves {
     47                     if length > 0 {
     48                         if self.reached[mv.to] == nil { // length increases, so only worse values are possible
     49                             self.reached[mv.to] = length
     50                         }
     51                     }
     52                      edges.fillNextMoves(prevMove: mv, nextMoves: &nextMoves, visited: &visited)
     53                 }
     54                 moves = nextMoves
     55                 length += 1
     56             }
     57         }
     58 
     59         var debugDescription: String {
     60             return self.reached.sorted{ $0.key < $1.key }.map{ "  ->($0.key): L=($0.value)" }.joined(separator: "
    ")
     61         }
     62 
     63         func length(to: Int, notFound: Int = -1) -> Int {
     64             guard to != 0 else {
     65                  return 0
     66             }
     67             return self.reached[to] ?? notFound
     68         }
     69     }
     70 
     71     class EdgeList: CustomDebugStringConvertible {
     72         private var colored = [EdgeColor:[Int:Set<Int>]]() // { color: { from: to } }
     73 
     74         init() {
     75         }
     76 
     77         var debugDescription: String {
     78             return self.colored.map{
     79                 "(EdgeColorHelper.toString($0.key)): " + $0.value.sorted{ $0.key < $1.key }.map{
     80                     "
      ($0.key) -> { " + $0.value.sorted().map{ String($0) }.joined(separator: " ") + " }"
     81                 }.joined()
     82             }.joined(separator: "
    ")
     83         }
     84 
     85          func add(edges: [[Int]], edgeColor: EdgeColor) {
     86               for crd in edges {
     87                 self.add(from: crd[0], to: crd[1], edgeColor: edgeColor)
     88             }
     89         }
     90 
     91         private func add(from: Int, to: Int, edgeColor: EdgeColor) {
     92             self.colored[edgeColor, default: [:]][from, default: Set<Int>()].insert(to)
     93         }
     94 
     95         func fillNextMoves(prevMove: MoveTo, nextMoves: inout [MoveTo], visited: inout Set<MoveTo>) {
     96             let nextColor: EdgeColor
     97             switch prevMove.edgeColor {
     98                 case .red:
     99                     nextColor = .blue
    100                 case .blue:
    101                       nextColor = .red
    102             }
    103 
    104             guard let edges = self.colored[nextColor] else {
    105                 return
    106             }
    107             guard let dests = edges[prevMove.to] else {
    108                 return
    109             }
    110 
    111             for to in dests {
    112                 let mv = MoveTo(from: prevMove.to, to: to, edgeColor: nextColor)
    113                  if visited.contains(mv) {
    114                       continue
    115                 }
    116 
    117                 visited.insert(mv)
    118                 nextMoves.append(mv)
    119             }
    120         }
    121     }
    122 
    123     func shortestAlternatingPaths(_ n: Int, _ red_edges: [[Int]], _ blue_edges: [[Int]]) -> [Int] {
    124         let edges = EdgeList()
    125           edges.add(edges: red_edges, edgeColor: .red)
    126         edges.add(edges: blue_edges, edgeColor: .blue)
    127 
    128         let dest = Reachability(edges: edges)
    129         var paths: [Int] = Array(repeating: 0, count: n)
    130         for i in 0..<paths.count {
    131             paths[i] = dest.length(to: i)
    132         }
    133         return paths
    134     }
    135 }
  • 相关阅读:
    Docker 学习4 Docker容器虚拟化网络概述
    Ceph 命令
    Day_09【常用API】扩展案例1_程序中使用一个长度为3的对象数组,存储用户的登录名和密码……
    Day_08【面向对象】扩展案例4_年龄为30岁的老王养了一只黑颜色的2岁的宠物……
    Day_08【面向对象】扩展案例3_使用多态的形式创建缉毒狗对象,调用缉毒方法和吼叫方法
    Day_08【面向对象】扩展案例2_测试旧手机新手机类,并给新手机实现玩游戏功能
    Day_08【面向对象】扩展案例1_测试项目经理类和程序员类
    用两个栈实现队列
    二叉树前序、中序、后序遍历相互求法
    洗牌
  • 原文地址:https://www.cnblogs.com/strengthen/p/11179555.html
Copyright © 2011-2022 走看看