[Swift]LeetCode399. 除法求值 | Evaluate Division
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10309042.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
Equations are given in the format A / B = k
, where A
and B
are variables represented as strings, and k
is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0
.
Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].
The input is: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries
, where equations.size() == values.size()
, and the values are positive. This represents the equations. Return vector<double>
.
According to the example above:
equations = [ ["a", "b"], ["b", "c"] ], values = [2.0, 3.0], queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
给出方程式 A / B = k
, 其中 A
和 B
均为代表字符串的变量, k
是一个浮点型数字。根据已知方程式求解问题,并返回计算结果。如果结果不存在,则返回 -1.0
。
示例 :
给定 a / b = 2.0, b / c = 3.0
问题: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
返回 [6.0, 0.5, -1.0, 1.0, -1.0 ]
输入为: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries
(方程式,方程式结果,问题方程式), 其中 equations.size() == values.size()
,即方程式的长度与方程式结果长度相等(程式与结果一一对应),并且结果值均为正数。以上为方程式的描述。 返回vector<double>
类型。
基于上述例子,输入如下:
equations(方程式) = [ ["a", "b"], ["b", "c"] ], values(方程式结果) = [2.0, 3.0], queries(问题方程式) = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
输入总是有效的。你可以假设除法运算中不会出现除数为0的情况,且不存在任何矛盾的结果。
8ms
1 class Solution { 2 func calcEquation(_ equations: [[String]], _ values: [Double], _ queries: [[String]]) -> [Double] { 3 var graph: [String : [(String, Double)]] = [:] 4 5 for i in 0..<equations.count { 6 let firstVar = equations[i][0] 7 let secondVar = equations[i][1] 8 9 if graph[firstVar] == nil { 10 graph[firstVar] = [] 11 } 12 13 if graph[secondVar] == nil { 14 graph[secondVar] = [] 15 } 16 17 graph[firstVar]!.append((secondVar, values[i])) 18 graph[secondVar]!.append((firstVar, 1 / values[i])) 19 } 20 21 var result: [Double] = [] 22 23 for querie in queries { 24 result.append(search(graph, querie[0], querie[1], [:], 1)) 25 } 26 27 return result 28 } 29 30 func search(_ graph: [String : [(String, Double)]], _ currentElement: String, _ element: String, _ searched: [String:Bool], _ sum: Double) -> Double { 31 if currentElement == element, graph[currentElement] != nil { 32 return sum 33 } 34 35 var updatedSearched = searched 36 updatedSearched[currentElement] = true 37 guard let children = graph[currentElement] else { 38 return -1 39 } 40 41 for child in children { 42 if updatedSearched[child.0] == nil { 43 let result = search(graph, child.0, element, updatedSearched, sum * child.1) 44 45 if result != -1 { 46 return result 47 } 48 } 49 } 50 51 return -1 52 } 53 }
12ms
1 class Solution { 2 var m:[String:[String:Double]] = [String:[String:Double]]() 3 func calcEquation(_ equations: [[String]], _ values: [Double], _ queries: [[String]]) -> [Double] { 4 var res:[Double] = [Double]() 5 for i in 0..<equations.count 6 { 7 if m[equations[i][0]] == nil 8 { 9 var item1:[String:Double] = [equations[i][1] : values[i]] 10 m[equations[i][0]] = item1 11 } 12 else 13 { 14 m[equations[i][0]]![equations[i][1]] = values[i] 15 } 16 17 if m[equations[i][1]] == nil 18 { 19 var item2:[String:Double] = [equations[i][0] : 1.0 / values[i]] 20 m[equations[i][1]] = item2 21 } 22 else 23 { 24 m[equations[i][1]]![equations[i][0]] = 1.0 / values[i] 25 } 26 27 } 28 for query in queries 29 { 30 var visited:Set<String> = Set<String>() 31 var t:Double = helper(query[0], query[1], &visited) 32 if t > 0.0 33 { 34 res.append(t) 35 } 36 else 37 { 38 res.append(-1.0) 39 } 40 } 41 return res 42 } 43 44 func helper(_ up:String,_ down:String,_ visited:inout Set<String>) -> Double 45 { 46 if m[up] == nil 47 { 48 return -1.0 49 } 50 if m[up]![down] != nil 51 { 52 return m[up]![down]! 53 } 54 55 var dic = m[up]! 56 var arrG = [String](dic.keys) 57 for a in arrG 58 { 59 if visited.contains(a) 60 { 61 continue 62 } 63 visited.insert(a) 64 var t:Double = helper(a, down, &visited) 65 if t > 0.0 66 { 67 return t * dic[a]! 68 } 69 } 70 return -1.0 71 } 72 }
12ms
1 class Solution { 2 func calcEquation(_ equations: [[String]], _ values: [Double], _ queries: [[String]]) -> [Double] { 3 4 var argumentsSet: Set<String> = Set<String>() 5 for pair in equations { 6 for argument in pair { 7 argumentsSet.insert(argument) 8 } 9 } 10 let argumentsArray = Array(argumentsSet) 11 let amountOfElements = argumentsArray.count 12 var matrix: [[Double?]] = [] 13 for i in 0..<amountOfElements { 14 var line: [Double?] = [] 15 for j in 0..<amountOfElements { 16 if let index = equations.firstIndex(of: [argumentsArray[i], argumentsArray[j]]) { 17 line.append(values[index]) 18 } else if let index = equations.firstIndex(of: [argumentsArray[j], argumentsArray[i]]) { 19 line.append(1.0/values[index]) 20 } else { 21 line.append(nil) 22 } 23 } 24 matrix.append(line) 25 } 26 for i in 0..<amountOfElements { 27 matrix = algorithmFloyd(matrix:matrix) 28 } 29 var resultArray: [Double] = [] 30 for pair in queries { 31 guard let index1 = argumentsArray.firstIndex(of:pair[0]), 32 let index2 = argumentsArray.firstIndex(of:pair[1]) else { 33 resultArray.append(-1) 34 continue} 35 let element = matrix[index1][index2] ?? -1.0 36 resultArray.append(element) 37 } 38 return resultArray 39 } 40 41 func algorithmFloyd(matrix: [[Double?]]) -> [[Double?]] { 42 var resultMatrix:[[Double?]] = [] 43 for i in 0..<matrix.count { 44 var line: [Double?] = [] 45 for j in 0..<matrix.count { 46 if let element = matrix[i][j] { 47 line.append(element) 48 } else { 49 var resultElement: Double? = nil 50 for k in 0..<matrix.count { 51 if let firstElement = matrix[i][k], 52 let secondElement = matrix[k][j] { 53 resultElement = firstElement*secondElement 54 break; 55 } 56 } 57 line.append(resultElement) 58 } 59 } 60 resultMatrix.append(line) 61 } 62 return resultMatrix 63 } 64 }
16ms
1 class Solution { 2 func calcEquation(_ equations: [[String]], _ values: [Double], _ queries: [[String]]) -> [Double] { 3 var graph: [String: [(String, Double)]] = [:] // stores key/val 4 var res: [Double] = [] 5 6 for i in 0..<equations.count { 7 let e = equations[i] 8 let n1 = e[0], n2 = e[1] 9 let v = values[i] 10 11 var l1 = graph[n1] ?? [] 12 l1.append((n2, v)) 13 graph[n1] = l1 14 var l2 = graph[n2] ?? [] 15 l2.append((n1, 1/v)) 16 graph[n2] = l2 17 } 18 19 for q in queries { 20 var visited: Set<String> = Set<String>() 21 // dfs 22 let start = q[0] 23 let end = q[1] 24 let r = self.dfs(start, end, graph, &visited) 25 res.append(r) 26 } 27 return res 28 } 29 30 private func dfs(_ start: String, _ end: String, _ graph: [String: [(String, Double)]], _ visited: inout Set<String>) -> Double { 31 defer { 32 visited.remove(start) 33 } 34 35 visited.insert(start) 36 if let l1 = graph[start] { 37 if start == end { return 1 } 38 for e in l1 { 39 if visited.contains(e.0) { continue } 40 let val = self.dfs(e.0, end, graph, &visited) 41 if val != -1 { 42 return val * e.1 43 } 44 } 45 } 46 return -1 47 } 48 }
20ms
1 class Edge { 2 var source: Node 3 var destination: Node 4 var weight: Double 5 6 init(source: Node, destination: Node, weight: Double) { 7 self.source = source 8 self.destination = destination 9 self.weight = weight 10 } 11 } 12 13 class Node { 14 var value: String 15 var edges: [Edge] 16 var visited: Bool 17 var currentWeight: Double 18 var currentParent: Node? 19 20 init(value: String) { 21 self.value = value 22 self.edges = [Edge]() 23 self.currentWeight = 0.0 24 self.visited = false 25 } 26 } 27 28 class Solution { 29 func calcEquation(_ equations: [[String]], _ values: [Double], _ queries: [[String]]) -> [Double] { 30 //TODO: input validation 31 32 var result = [Double]() 33 var nodeDict = [String: Node]() 34 var nodes = [Node]() 35 36 for (index,equation) in equations.enumerated() { 37 let first = equation[0] 38 let second = equation[1] 39 let value = values[index] 40 41 var firstNode = nodeDict[first] 42 if firstNode == nil { 43 firstNode = Node.init(value: first) 44 nodeDict[first] = firstNode 45 nodes.append(firstNode!) 46 } 47 var secondNode = nodeDict[second] 48 if secondNode == nil { 49 secondNode = Node.init(value: second) 50 nodeDict[second] = secondNode 51 nodes.append(secondNode!) 52 } 53 54 let firstEdge = Edge.init(source: firstNode!, destination: secondNode!, weight:value) 55 let secondEdge = Edge.init(source: secondNode!, destination: firstNode!, weight:1.0 / value) 56 firstNode!.edges.append(firstEdge) 57 secondNode!.edges.append(secondEdge) 58 } 59 60 for query in queries { 61 for node in nodes { 62 node.currentParent = nil 63 node.currentWeight = 0.0 64 node.visited = false 65 } 66 let first = query[0] 67 let second = query[1] 68 69 let firstNode = nodeDict[first] 70 if firstNode == nil { 71 result.append(-1.0) 72 continue 73 } 74 let secondNode = nodeDict[second] 75 if secondNode == nil { 76 result.append(-1.0) 77 continue 78 } 79 80 if firstNode?.value == secondNode?.value { 81 result.append(1.0) 82 continue 83 } 84 var queue = [Edge]() 85 for edge in firstNode!.edges { 86 edge.destination.currentParent = firstNode! 87 edge.destination.currentWeight = edge.weight 88 edge.source.visited = true 89 queue.append(edge) 90 } 91 var found = false 92 while queue.count > 0 { 93 let edge = queue[0] 94 queue.remove(at: 0) 95 var currentNode = edge.destination 96 currentNode.visited = true 97 if currentNode.value == secondNode!.value { 98 var eq = 1.0 99 while currentNode.currentParent != nil { 100 eq = eq * currentNode.currentWeight 101 currentNode = currentNode.currentParent! 102 } 103 result.append(eq) 104 found = true 105 break 106 } 107 for subedge in currentNode.edges { 108 if !subedge.destination.visited { 109 subedge.destination.currentParent = currentNode 110 subedge.destination.currentWeight = subedge.weight 111 queue.append(subedge) 112 } 113 } 114 } 115 if !found { 116 result.append(-1.0) 117 } 118 } 119 120 return result 121 } 122 }