[Swift]LeetCode787. K 站中转内最便宜的航班 | Cheapest Flights Within K Stops
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: https://www.cnblogs.com/strengthen/p/10545382.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
There are n
cities connected by m
flights. Each fight starts from city u
and arrives at v
with a price w
.
Now given all the cities and flights, together with starting city src
and the destination dst
, your task is to find the cheapest price from src
to dst
with up to k
stops. If there is no such route, output -1
.
Example 1: Input: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 1 Output: 200 Explanation: The graph looks like this:
The cheapest price from city0
to city2
with at most 1 stop costs 200, as marked red in the picture.
Example 2: Input: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 0 Output: 500 Explanation: The graph looks like this:
The cheapest price from city0
to city2
with at most 0 stop costs 500, as marked blue in the picture.
Note:
- The number of nodes
n
will be in range[1, 100]
, with nodes labeled from0
ton
- 1
. - The size of
flights
will be in range[0, n * (n - 1) / 2]
. - The format of each flight will be
(src,
dst
, price)
. - The price of each flight will be in the range
[1, 10000]
. k
is in the range of[0, n - 1]
.- There will not be any duplicated flights or self cycles.
有 n
个城市通过 m
个航班连接。每个航班都从城市 u
开始,以价格 w
抵达 v
。
现在给定所有的城市和航班,以及出发城市 src
和目的地 dst
,你的任务是找到从 src
到 dst
最多经过 k
站中转的最便宜的价格。 如果没有这样的路线,则输出 -1
。
示例 1: 输入: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 1 输出: 200 解释: 城市航班图如下
从城市 0 到城市 2 在 1 站中转以内的最便宜价格是 200,如图中红色所示。
示例 2: 输入: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 0 输出: 500 解释: 城市航班图如下
从城市 0 到城市 2 在 0 站中转以内的最便宜价格是 500,如图中蓝色所示。
提示:
n
范围是[1, 100]
,城市标签从0
到n
- 1
.- 航班数量范围是
[0, n * (n - 1) / 2]
. - 每个航班的格式
(src,
dst
, price)
. - 每个航班的价格范围是
[1, 10000]
. k
范围是[0, n - 1]
.- 航班没有重复,且不存在环路
68ms
1 class Solution { 2 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 3 var grid = [[Int]](repeating: [Int](repeating: 0, count: n), count: n) 4 for flight in flights { 5 grid[flight[1]][flight[0]] = flight[2] 6 } 7 var k = K 8 var dsts = [(dst, 0)], nextDst = [(Int, Int)]() 9 var ans = Int.max 10 while dsts.count > 0 && k >= 0 { 11 let (validDst, v) = dsts.removeFirst() 12 for i in grid[validDst].indices { 13 if grid[validDst][i] != 0 { 14 if i == src { ans = min(ans, grid[validDst][i] + v) } 15 else { 16 if ans >= grid[validDst][i] + v { 17 nextDst.append((i, grid[validDst][i] + v)) 18 } 19 } 20 } 21 } 22 if dsts.count == 0 { 23 dsts = nextDst 24 nextDst.removeAll() 25 k -= 1 26 } 27 } 28 return ans == Int.max ? -1 : ans 29 } 30 31 func mainBFS(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 32 33 var queue = Queue<City>() 34 queue.enqueue(src) 35 36 var visited = Set<City>() 37 var stops = 0 38 var cheapestPrice = 0 39 40 let graph = genGraph(flights) 41 42 while let fromCity = queue.dequeue() { 43 44 if fromCity == dst { 45 return cheapestPrice 46 } 47 48 if stops == K { 49 // check if we can make it to the destination 50 // or return -1 since we will have exceeded max layovers 51 var priceToDst = -1 52 if let nextCities = graph[fromCity] { 53 var i = 0 54 var foundDst = false 55 while i < nextCities.count && !foundDst { 56 if nextCities[i] == dst { 57 priceToDst = cheapestPrice + price(flights, from: fromCity, to: nextCities[i]) 58 foundDst = true 59 } 60 i += 1 61 } 62 } 63 return priceToDst 64 } 65 66 // Look ahead and choose the next cheapest flight (Dijkstra's algorithm) 67 // Important! This only works with positive edge values. 68 if let toCity = nextCheapestCity(from: fromCity, graph: graph, flights: flights) { 69 70 // Don't revisit a city we have already traveled to 71 if !visited.contains(toCity) { 72 // visited.insert(toCity) 73 74 // Cheapest prices so far 75 cheapestPrice += price(flights, from: fromCity, to: toCity) 76 77 // Stops 78 stops += 1 79 80 // Enqueue next city 81 queue.enqueue(toCity) 82 } 83 } 84 } 85 print("returned here with cheapest price -> \(cheapestPrice)") 86 return -1 87 } 88 89 func mainDFS(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 90 var minPrice = Int.max 91 var curPrice = 0 92 var curLayovers = 0 93 var visited = Set<Int>() 94 var found = false 95 let graph = genGraph(flights) 96 visited.insert(src) 97 dfs(flights, dst: dst, k: K, graph: graph, vertex: src, curPrice: &curPrice, curLayovers: &curLayovers, visited: &visited, found: &found, minPrice: &minPrice) 98 return found ? minPrice : -1 99 } 100 101 func dfs(_ flights: [[Int]], dst: Int, k: Int, graph: [City: [City]], vertex: Int, curPrice: inout Int, curLayovers: inout Int, visited: inout Set<Int>, found: inout Bool, minPrice: inout Int) { 102 if vertex == dst { 103 found = true 104 if curPrice < minPrice { 105 minPrice = curPrice 106 } 107 return 108 } 109 if curLayovers > k { 110 return 111 } 112 113 if let destinations = graph[vertex] { 114 destinations.forEach { neighbor in 115 if !visited.contains(neighbor) { 116 var toPrice = price(flights, from: vertex, to: neighbor) 117 curPrice += toPrice 118 curLayovers += 1 119 dfs(flights, dst: dst, k: k, graph: graph, vertex: neighbor, curPrice: &curPrice, curLayovers: &curLayovers, visited: &visited, found: &found, minPrice: &minPrice) 120 visited.remove(neighbor) 121 curPrice -= toPrice 122 curLayovers -= 1 123 } 124 } 125 } 126 127 } 128 129 // Helpers 130 131 typealias City = Int 132 typealias Price = Int 133 134 struct Queue<Element> { 135 var storage = [Element]() 136 mutating func enqueue(_ element: Element) { 137 self.storage.append(element) 138 } 139 mutating func dequeue() -> Element? { 140 guard self.storage.count > 0 else { return nil } 141 return self.storage.removeFirst() 142 } 143 } 144 145 func genGraph(_ flights: [[Int]]) -> [City: [City]] { 146 var graph = [Int: [Int]]() 147 flights.forEach { flight in 148 let from = flight[0] 149 let to = flight[1] 150 if var edges = graph[from] { 151 edges.append(to) 152 graph[from] = edges 153 } else { 154 graph[from] = [to] 155 } 156 } 157 return graph 158 } 159 160 func price(_ flights: [[Int]], from: Int, to: Int) -> Int { 161 var i = 0 162 while i < flights.count { 163 let flight = flights[i] 164 if from == flight[0], to == flight[1] { 165 return flight[2] 166 } 167 i += 1 168 } 169 return -1 170 } 171 172 // Note: This can be done when creating the graph instead for the BFS solution to improve performance 173 func nextCheapestCity(from city: City, graph: [City: [City]], flights: [[Int]]) -> City? { 174 var nextCity: City? 175 var minPrice = Int.max 176 if let toCities = graph[city] { 177 toCities.forEach { toCity in 178 let priceToCity = price(flights, from: city, to: toCity) 179 if priceToCity < minPrice { 180 minPrice = priceToCity 181 nextCity = toCity 182 } 183 } 184 } 185 return nextCity 186 } 187 // Helpers - end 188 }
76ms
1 class Solution { 2 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 3 var grid = [[Int]](repeating: [Int](repeating: 0, count: n), count: n) 4 for flight in flights { 5 grid[flight[1]][flight[0]] = flight[2] 6 } 7 var k = K 8 var dsts = [(dst, 0)], nextDst = [(Int, Int)]() 9 var ans = Int.max 10 while dsts.count > 0 && k >= 0 { 11 let (validDst, v) = dsts.removeFirst() 12 for i in grid[validDst].indices { 13 if grid[validDst][i] != 0 { 14 if i == src { ans = min(ans, grid[validDst][i] + v) } 15 else { 16 if ans >= grid[validDst][i] + v { 17 nextDst.append((i, grid[validDst][i] + v)) 18 } 19 } 20 } 21 } 22 23 if dsts.count == 0 { 24 dsts = nextDst 25 nextDst.removeAll() 26 k -= 1 27 } 28 } 29 return ans == Int.max ? -1 : ans 30 } 31 }
1 class Solution { 2 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 3 var dp:[Double] = [Double](repeating:1e9,count:n) 4 dp[src] = 0 5 for i in 0...K 6 { 7 var t:[Double] = dp 8 for x in flights 9 { 10 t[x[1]] = min(t[x[1]], dp[x[0]] + Double(x[2])) 11 } 12 dp = t 13 } 14 return (dp[dst] >= 1e9) ? -1 : Int(dp[dst]) 15 } 16 }
96ms
1 class Solution { 2 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 3 4 5 let maxValue = 2147483647 6 7 var ShortestPath = [Int](repeating: maxValue, count: n) 8 ShortestPath[src] = 0 9 10 for _ in 0...K{ 11 var currentShortestPath = ShortestPath 12 13 for i in 0..<flights.count{ 14 let flight = flights[i] 15 let originCity = flight[0] 16 let destinationCity = flight[1] 17 let flightCost = flight[2] 18 19 20 21 currentShortestPath[destinationCity] = min(currentShortestPath[destinationCity], 22 ShortestPath[originCity] + flightCost) 23 24 } 25 ShortestPath = currentShortestPath 26 } 27 28 29 if ShortestPath[dst] == maxValue{ 30 return -1 31 }else{ 32 return ShortestPath[dst] 33 } 34 } 35 }
100ms
1 class Solution { 2 typealias Flight = (dst: Int, cost: Int) 3 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ start: Int, _ end: Int, _ k: Int) -> Int { 4 guard flights.isEmpty == false else { 5 return 0 6 } 7 var dict: [Int: [Flight]] = [:] 8 for flight in flights { 9 dict[flight[0], default: []].append((flight[1], flight[2])) 10 } 11 12 var res = Int.max 13 var queue: [Flight] = [] 14 queue.append((start, 0)) 15 var stops = -1 16 17 while queue.isEmpty == false { 18 let n = queue.count 19 for _ in 0..<n { 20 let curFlight = queue.removeFirst() 21 let curStop = curFlight.dst 22 let cost = curFlight.cost 23 if curStop == end { 24 res = min(res, cost) 25 continue 26 } 27 for flight in (dict[curStop] ?? []) { 28 if cost + flight.cost > res { 29 continue 30 } 31 queue.append((flight.dst, cost + flight.cost)) 32 } 33 } 34 stops += 1 35 if stops > k { 36 break 37 } 38 } 39 return (res == Int.max) ? -1 : res 40 } 41 }
136ms
1 class Solution { 2 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 3 var flightsMap = Dictionary<Int, Array<Flight>>() 4 var cache = Dictionary<CacheState, Int>() 5 for flight in flights { 6 let stFlight = Flight(destination: flight[1], cost: flight[2]) 7 if var array = flightsMap[flight[0]] { 8 array.append(stFlight) 9 flightsMap[flight[0]] = array 10 } else { 11 flightsMap[flight[0]] = [stFlight] 12 } 13 } 14 let ans = dfs(K, src, dst, flightsMap, &cache) 15 if ans == Int.max { return -1 } 16 return ans 17 } 18 func dfs( 19 _ remainingK: Int, 20 _ currentNode: Int, 21 _ dst: Int, 22 _ flightsMap: Dictionary<Int, Array<Flight>>, 23 _ cache: inout Dictionary<CacheState, Int>) -> Int { 24 if currentNode == dst { return 0 } 25 guard remainingK >= 0 else { return Int.max } 26 var cacheState = CacheState(source: currentNode, K: remainingK) 27 if let val = cache[cacheState] { return val } 28 var ans = Int.max 29 guard let array = flightsMap[currentNode] else { return Int.max } 30 for flight in array { 31 let curAns = dfs(remainingK - 1, flight.destination, dst, flightsMap, &cache) 32 if curAns != Int.max { 33 ans = min(ans, curAns + flight.cost) 34 } 35 } 36 cache[cacheState] = ans 37 return ans 38 } 39 } 40 41 struct Flight { 42 let destination: Int 43 let cost: Int 44 } 45 struct CacheState: Hashable { 46 let source: Int 47 let K: Int 48 }
152ms
1 class Solution { 2 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 3 let dict = flights.reduce(into: [Int: [(Int, Int)]]()) { 4 $0[$1[0], default:[]].append(($1[1], $1[2])) 5 } 6 var cache: [[Int?]] = Array(repeating: Array(repeating: nil, count: K+1), count: n) 7 let c = dfs(dict, src, dst, K, &cache) 8 return c 9 } 10 11 func dfs(_ flights: [Int: [(Int, Int)]], _ src: Int, _ dst: Int, _ K: Int, _ cache: inout [[Int?]]) -> Int { 12 guard src != dst else { return 0 } 13 guard K >= 0 else { return -1 } 14 var m : Int? 15 if let dests = flights[src] { 16 for f in dests { 17 let c = cache[f.0][K] ?? dfs(flights, f.0, dst, K-1, &cache) 18 if c != -1 { 19 cache[f.0][K] = c 20 m = min(m ?? Int.max, c+f.1) 21 } else { 22 cache[f.0][K] = -1 23 } 24 } 25 } 26 return m ?? -1 27 } 28 }
156ms
1 class Solution { 2 var res = Int.max 3 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 4 var graph: [Int: [(Int, Int)]] = [:] 5 6 for f in flights { 7 let start = f[0], end = f[1], price = f[2] 8 graph[start, default: []].append((end, price)) 9 } 10 var visited = Set<Int>() 11 var dp: [Int: Int] = [:] 12 dfs(graph, &dp, 0, &visited, src, dst, K) 13 return res == Int.max ? -1 : res 14 } 15 16 private func dfs(_ graph: [Int: [(Int, Int)]], _ dp: inout [Int: Int], _ cost: Int, _ visited: inout Set<Int>, _ start: Int, _ end: Int, _ remaining: Int) { 17 if start == end { 18 res = min(cost, res) 19 } 20 21 if remaining < 0 || cost >= res { 22 return 23 } 24 25 if let lowest = dp[start] { 26 if lowest < cost { 27 return 28 } 29 } 30 dp[start] = cost 31 32 var forwardCost = Int.max 33 if let outgoing = graph[start] { 34 for edge in outgoing { 35 dfs(graph, &dp, cost + edge.1, &visited, edge.0, end, remaining - 1) 36 } 37 } 38 } 39 }
288ms
1 class Solution { 2 var dp = [[Int]]() 3 var graph = [[Int]]() 4 5 func find(_ flights: [[Int]], _ src: Int, _ dst: Int, _ k: Int, _ n: Int) -> Int { 6 if src == dst { 7 dp[src][k] = 0 8 return dp[src][k] 9 } 10 if k == 0 { 11 dp[dst][k] = graph[dst][src] 12 return dp[dst][k] 13 } 14 if dp[dst][k] != Int.max { 15 return dp[dst][k] 16 } 17 18 for i in 0..<n { 19 if graph[dst][i] != Int.max && find(flights, src, i, k-1, n) != Int.max { 20 dp[dst][k] = min(dp[dst][k], graph[dst][i] + find(flights, src, i, k-1, n)) 21 } 22 } 23 return dp[dst][k] 24 } 25 26 func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ K: Int) -> Int { 27 dp = [[Int]](repeating: [Int](repeating: Int.max, count: K+1), count: n) 28 graph = [[Int]](repeating: [Int](repeating: Int.max, count: n), count: n) 29 for f in flights { 30 graph[f[1]][f[0]] = f[2] 31 } 32 return find(flights, src, dst, K, n) == Int.max ? -1 : dp[dst][K] 33 } 34 }