1. 程式人生 > >[Swift]LeetCode332. 重新安排行程 | Reconstruct Itinerary

[Swift]LeetCode332. 重新安排行程 | Reconstruct Itinerary

Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus, the itinerary must begin with JFK.

Note:

  1. If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary ["JFK", "LGA"]
     has a smaller lexical order than ["JFK", "LGB"].
  2. All airports are represented by three capital letters (IATA code).
  3. You may assume all tickets form at least one valid itinerary.

Example 1:

Input: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Output: ["JFK", "MUC", "LHR", "SFO", "SJC"]

Example 2:

Input: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Output: ["JFK","ATL","JFK","SFO","ATL","SFO"]
Explanation: Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"].
             But it is larger in lexical order.

給定一個機票的字串二維陣列 [from, to]

,子陣列中的兩個成員分別表示飛機出發和降落的機場地點,對該行程進行重新規劃排序。所有這些機票都屬於一個從JFK(肯尼迪國際機場)出發的先生,所以該行程必須從 JFK 出發。

說明:

  1. 如果存在多種有效的行程,你可以按字元自然排序返回最小的行程組合。例如,行程 ["JFK", "LGA"] 與 ["JFK", "LGB"] 相比就更小,排序更靠前
  2. 所有的機場都用三個大寫字母表示(機場程式碼)。
  3. 假定所有機票至少存在一種合理的行程。

示例 1:

輸入: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
輸出: ["JFK", "MUC", "LHR", "SFO", "SJC"]

示例 2:

輸入: [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
輸出: ["JFK","ATL","JFK","SFO","ATL","SFO"]
解釋: 另一種有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"]。但是它自然排序更大更靠後。

144ms
 1 class Solution {
 2     var graph: [String: [String]] = [:]
 3     var route: [String] = []
 4     func findItinerary(_ tickets: [[String]]) -> [String] {
 5         
 6         for t in tickets {
 7             var city = graph[t[0]] ?? []
 8             city.append(t[1])
 9             graph[t[0]] = city
10         }
11         
12         for key in graph.keys {
13             graph[key]?.sort()
14         }
15         self.visit("JFK")
16         return self.route
17     }
18     
19     private func visit(_ city: String) {
20         if let dests = graph[city] {
21             while !graph[city]!.isEmpty {
22                 let dest = graph[city]!.removeFirst()
23                 self.visit(dest)
24             }
25         }
26         self.route.insert(city, at: 0)
27     }
28 }

568ms

  1 class Solution {
  2      func findItinerary(_ tickets: [[String]]) -> [String] {
  3         
  4         let graph = buildGraph(tickets)
  5         var res = [String]()
  6         dfs(graph, from: "JFK",0, &res)
  7         
  8         return res
  9     }
 10 
 11     @discardableResult func dfs(_ graph : Graph<String>, from : String ,_ visitedCount : Int, _ res : inout [String]) -> Bool {
 12         res.append(from)
 13         if visitedCount == graph.edges.count {
 14             return true
 15         }
 16         let edges = graph.edgesFrom(graph.createVertex(from)).sorted{$0.to.data < $1.to.data}
 17         for edge in edges where edge.visited == false {
 18             edge.visited = true
 19             if dfs(graph, from: edge.to.data, visitedCount+1, &res) == true {
 20                 return true
 21             }
 22             edge.visited = false
 23         }
 24         res.removeLast()
 25         return false
 26         
 27     }
 28     
 29     func buildGraph(_ tickets : [[String]]) -> Graph<String> {
 30         let graph = Graph<String>()
 31         for i in 0..<tickets.count {
 32             let ticket = tickets[i]
 33             let from = graph.createVertex(ticket[0])
 34             let to = graph.createVertex(ticket[1])
 35             graph.addDirectedEdge(from, to: to, withWeight: Double(i))
 36         }
 37         return graph
 38     }
 39     //===================實現Graph的分割線======================
 40     struct Vertex<T> : Equatable,Hashable where T : Hashable {
 41         var data : T
 42         var index : Int
 43         
 44         public var description: String {
 45             return "\(index):\(data)"
 46         }
 47     }
 48 
 49     public class Edge<T>: Equatable,Hashable where T: Hashable {
 50         public static func == (lhs: Solution.Edge<T>, rhs: Solution.Edge<T>) -> Bool {
 51             return lhs.from == rhs.from && lhs.to == rhs.to && lhs.weight == rhs.weight
 52         }
 53         
 54         public let from: Vertex<T>
 55         public let to: Vertex<T>
 56         
 57         public let weight:Double?
 58         
 59         public var visited : Bool
 60         
 61         public var hashValue:Int {
 62             var string = "\(from.description)\(to.description)"
 63             if weight != nil{
 64                 string.append("\(weight!)")
 65             }
 66             return string.hashValue
 67         }
 68         
 69         init(from: Vertex<T>, to: Vertex<T>, weight: Double?, visited: Bool) {
 70             self.from = from
 71             self.to = to
 72             self.weight = weight
 73             self.visited = visited
 74         }
 75     }
 76     
 77 
 78     
 79     private class EdgeList<T> where T: Hashable {
 80         
 81         var vertex: Vertex<T>
 82         var edges: [Edge<T>]?
 83         
 84         init(vertex: Vertex<T>) {
 85             self.vertex = vertex
 86         }
 87         
 88         func addEdge(_ edge: Edge<T>) {
 89             edges?.append(edge)
 90         }
 91         
 92     }
 93     
 94     
 95     class Graph<T> where T : Hashable {
 96         var vertices : [Vertex<T>] {
 97             var vertices = [Vertex<T>]()
 98             for edgeList in adjacencyList {
 99                 vertices.append(edgeList.vertex)
100             }
101             return vertices
102         }
103         
104         private var adjacencyList: [EdgeList<T>] = []
105         
106         open var edges: [Edge<T>] = [Edge<T>]()
107 
108         open func addDirectedEdge(_ from: Vertex<T>, to: Vertex<T>, withWeight weight: Double?) {
109             // works
110             let edge = Edge(from: from, to: to, weight: weight, visited: false)
111             let edgeList = adjacencyList[from.index]
112             if edgeList.edges != nil {
113                 edgeList.addEdge(edge)
114             } else {
115                 edgeList.edges = [edge]
116             }
117             edges.append(edge)
118         }
119         
120         open func createVertex(_ data: T) -> Vertex<T> {
121            
122             let matchingVertices = vertices.filter { vertex in
123                 return vertex.data == data
124             }
125             
126             if matchingVertices.count > 0 {
127                 return matchingVertices.last!
128             }
129 
130             let vertex = Vertex(data: data, index: adjacencyList.count)
131             adjacencyList.append(EdgeList(vertex: vertex))
132             return vertex
133         }
134         
135         open func edgesFrom(_ sourceVertex: Vertex<T>) -> [Edge<T>] {
136             return adjacencyList[sourceVertex.index].edges ?? []
137         }
138                 
139     }
140 }