Skip to content

Commit 6c99692

Browse files
authored
Merge pull request #339 from soapyigu/Graph
Graph
2 parents d9d4389 + 4813fac commit 6c99692

File tree

2 files changed

+88
-39
lines changed

2 files changed

+88
-39
lines changed

Graph/AlienDictionary.swift

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,68 +9,65 @@
99

1010
class AlienDictionary {
1111
func alienOrder(_ words: [String]) -> String {
12-
var res = "", queueChars = [Character]()
13-
var (indegrees, charToChars) = initGraph(words)
12+
var (inDegrees, toChars) = buildGraph(words)
1413

15-
indegrees.keys.filter { indegrees[$0] == 0 }.forEach { queueChars.append($0) }
14+
var queue = inDegrees.keys.filter { inDegrees[$0] == 0 }
15+
var res = ""
1616

17-
while !queueChars.isEmpty {
18-
let char = queueChars.removeFirst()
19-
res.append(char)
17+
while !queue.isEmpty {
18+
let char = queue.removeFirst()
2019

21-
guard let toChars = charToChars[char] else {
22-
fatalError("Init Graph Error")
23-
}
20+
res.append(char)
2421

25-
for toChar in toChars {
26-
guard let indegree = indegrees[toChar] else {
27-
fatalError("Init Graph Error")
28-
}
22+
for nextChar in toChars[char]! {
23+
inDegrees[nextChar]! -= 1
2924

30-
indegrees[toChar] = indegree - 1
31-
if indegree == 1 {
32-
queueChars.append(toChar)
25+
if inDegrees[nextChar] == 0 {
26+
queue.append(nextChar)
3327
}
3428
}
3529
}
3630

37-
return res.count == indegrees.count ? res : ""
31+
return res.count == inDegrees.count ? res : ""
3832
}
3933

40-
private func initGraph(_ words: [String]) -> ([Character: Int], [Character: [Character]]) {
41-
var indegrees = [Character: Int](), charToChars = [Character: [Character]]()
34+
private func buildGraph(_ words: [String]) -> ([Character: Int], [Character: [Character]]) {
35+
// init inDegrees and toChars
36+
var inDegrees = [Character: Int](), toChars = [Character: [Character]]()
4237

43-
// init indegress and charToChars
4438
words.forEach { word in
4539
word.forEach { char in
46-
indegrees[char] = 0
47-
charToChars[char] = [Character]()
48-
}
40+
inDegrees[char] = 0
41+
toChars[char] = [Character]()
42+
}
4943
}
5044

51-
// refactor indegress and charToChars based on words
45+
// update based on orders
5246
for i in 0..<words.count - 1 {
53-
let currentWord = Array(words[i]), nextWord = Array(words[i + 1])
54-
var j = 0
55-
56-
while j < currentWord.count && j < nextWord.count {
57-
let currentChar = currentWord[j], nextChar = nextWord[j]
58-
59-
if nextChar == currentChar {
60-
j += 1
47+
let left = Array(words[i]), right = Array(words[i + 1])
48+
49+
for j in 0..<min(left.count, right.count) {
50+
if left[j] == right[j] {
51+
52+
// invalid use case
53+
if j + 1 == right.count && right.count < left.count {
54+
return ([Character: Int](), [Character: [Character]]())
55+
}
56+
6157
continue
6258
}
63-
if let toChars = charToChars[currentChar], toChars.contains(nextChar) {
59+
60+
if toChars[left[j]]!.contains(right[j]) {
6461
break
6562
}
66-
67-
indegrees[nextChar, default: 0] += 1
68-
charToChars[currentChar, default: [Character]()].append(nextChar)
63+
64+
inDegrees[right[j]]! += 1
65+
toChars[left[j]]!.append(right[j])
6966
break
67+
7068
}
71-
7269
}
73-
74-
return (indegrees, charToChars)
70+
71+
return (inDegrees, toChars)
7572
}
7673
}

Graph/CheapestFlightsKStops.swift

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Question Link: https://leetcode.com/problems/cheapest-flights-within-k-stops/
3+
* Primary idea: Topological sort + BFS.
4+
* Build a graph with each srouce and destination as an edge. Put the source as the head node for the queue, visit every possible destinaiton and update the result with the possible smallest value.
5+
*
6+
* Time Complexity: O(n * (n - 1) + K), Space Complexity: O(n * (n - 1)),
7+
* n represents number of the cities
8+
*/
9+
10+
class CheapestFlightsKStops {
11+
func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ k: Int) -> Int {
12+
var srcDestinations = buildGraph(flights)
13+
var queue = [(src, 0)], dstPrice = [Int: Int](), stopCount = 0
14+
15+
while !queue.isEmpty && stopCount < k + 1 {
16+
17+
let currentQueueLen = queue.count
18+
19+
for _ in 0..<currentQueueLen {
20+
let (from, fromPrice) = queue.removeFirst()
21+
22+
guard let destinations = srcDestinations[from] else {
23+
continue
24+
}
25+
26+
for (to, price) in destinations {
27+
if let prevPrice = dstPrice[to], prevPrice <= fromPrice + price {
28+
continue
29+
} else {
30+
dstPrice[to] = fromPrice + price
31+
queue.append((to, fromPrice + price))
32+
}
33+
}
34+
35+
}
36+
stopCount += 1
37+
}
38+
39+
return dstPrice[dst] ?? -1
40+
}
41+
42+
// src -> (dst, price)
43+
private func buildGraph(_ flights: [[Int]]) -> [Int: [(Int, Int)]] {
44+
var srcDestinations = [Int: [(Int, Int)]]()
45+
46+
for flight in flights {
47+
srcDestinations[flight[0], default:[(Int, Int)]()].append((flight[1], flight[2]))
48+
}
49+
50+
return srcDestinations
51+
}
52+
}

0 commit comments

Comments
 (0)