Skip to content

Commit

Permalink
Merge pull request soapyigu#339 from soapyigu/Graph
Browse files Browse the repository at this point in the history
Graph
  • Loading branch information
soapyigu authored Aug 31, 2022
2 parents d9d4389 + 4813fac commit 6c99692
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 39 deletions.
75 changes: 36 additions & 39 deletions Graph/AlienDictionary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,68 +9,65 @@

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

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

while !queueChars.isEmpty {
let char = queueChars.removeFirst()
res.append(char)
while !queue.isEmpty {
let char = queue.removeFirst()

guard let toChars = charToChars[char] else {
fatalError("Init Graph Error")
}
res.append(char)

for toChar in toChars {
guard let indegree = indegrees[toChar] else {
fatalError("Init Graph Error")
}
for nextChar in toChars[char]! {
inDegrees[nextChar]! -= 1

indegrees[toChar] = indegree - 1
if indegree == 1 {
queueChars.append(toChar)
if inDegrees[nextChar] == 0 {
queue.append(nextChar)
}
}
}

return res.count == indegrees.count ? res : ""
return res.count == inDegrees.count ? res : ""
}

private func initGraph(_ words: [String]) -> ([Character: Int], [Character: [Character]]) {
var indegrees = [Character: Int](), charToChars = [Character: [Character]]()
private func buildGraph(_ words: [String]) -> ([Character: Int], [Character: [Character]]) {
// init inDegrees and toChars
var inDegrees = [Character: Int](), toChars = [Character: [Character]]()

// init indegress and charToChars
words.forEach { word in
word.forEach { char in
indegrees[char] = 0
charToChars[char] = [Character]()
}
inDegrees[char] = 0
toChars[char] = [Character]()
}
}

// refactor indegress and charToChars based on words
// update based on orders
for i in 0..<words.count - 1 {
let currentWord = Array(words[i]), nextWord = Array(words[i + 1])
var j = 0

while j < currentWord.count && j < nextWord.count {
let currentChar = currentWord[j], nextChar = nextWord[j]

if nextChar == currentChar {
j += 1
let left = Array(words[i]), right = Array(words[i + 1])

for j in 0..<min(left.count, right.count) {
if left[j] == right[j] {

// invalid use case
if j + 1 == right.count && right.count < left.count {
return ([Character: Int](), [Character: [Character]]())
}

continue
}
if let toChars = charToChars[currentChar], toChars.contains(nextChar) {

if toChars[left[j]]!.contains(right[j]) {
break
}

indegrees[nextChar, default: 0] += 1
charToChars[currentChar, default: [Character]()].append(nextChar)
inDegrees[right[j]]! += 1
toChars[left[j]]!.append(right[j])
break

}

}

return (indegrees, charToChars)
return (inDegrees, toChars)
}
}
52 changes: 52 additions & 0 deletions Graph/CheapestFlightsKStops.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Question Link: https://leetcode.com/problems/cheapest-flights-within-k-stops/
* Primary idea: Topological sort + BFS.
* 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.
*
* Time Complexity: O(n * (n - 1) + K), Space Complexity: O(n * (n - 1)),
* n represents number of the cities
*/

class CheapestFlightsKStops {
func findCheapestPrice(_ n: Int, _ flights: [[Int]], _ src: Int, _ dst: Int, _ k: Int) -> Int {
var srcDestinations = buildGraph(flights)
var queue = [(src, 0)], dstPrice = [Int: Int](), stopCount = 0

while !queue.isEmpty && stopCount < k + 1 {

let currentQueueLen = queue.count

for _ in 0..<currentQueueLen {
let (from, fromPrice) = queue.removeFirst()

guard let destinations = srcDestinations[from] else {
continue
}

for (to, price) in destinations {
if let prevPrice = dstPrice[to], prevPrice <= fromPrice + price {
continue
} else {
dstPrice[to] = fromPrice + price
queue.append((to, fromPrice + price))
}
}

}
stopCount += 1
}

return dstPrice[dst] ?? -1
}

// src -> (dst, price)
private func buildGraph(_ flights: [[Int]]) -> [Int: [(Int, Int)]] {
var srcDestinations = [Int: [(Int, Int)]]()

for flight in flights {
srcDestinations[flight[0], default:[(Int, Int)]()].append((flight[1], flight[2]))
}

return srcDestinations
}
}

0 comments on commit 6c99692

Please sign in to comment.