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=3,c/d=6,a/c=2,忘考虑a/c这层关系带来的大小放缩了。如果理解成一个拓扑排序,肯定是可以解的。评论区看到一种更好的有向并查集解法:a/b=3,那么并查集f[b]=(b,1),f[a]=(b,3);c/d=6,那么并查集f[d]=(d,1),f[c]=(d,6); a/c的时候,a原来指向b,而c是指向d的,所以f[b]=(d,6*2/3),其中3是从b到a的换算,所以是除3。
from collections import defaultdict
class Solution:
def calcEquation(self, equations, values, queries):
p = {}
def find(x):
if x not in p:
p[x] = (x, 1.0)
elif p[x][0] != x:
v = p[x][1]
pxt = find(p[x][0])
pxn,pxv = pxt[0],pxt[1]
p[x] = (pxn, v * pxv)
return p[x]
def union(x, y, v):
pxt, pyt = find(x), find(y)
pxn,pxv,pyn,pyv = pxt[0],pxt[1],pyt[0],pyt[1]
if pxn != pyn:
p[pxn] = (pyn, v * pyv / pxv)
for (a, b), v in zip(equations, values):
union(a, b, v)
print(p)
print('-------------------')
ans = []
for a, b in queries:
res = p[a][1] / p[b][1] if (a in p and b in p and find(a)[0] == find(b)[0]) else -1.0
ans.append(res)
return ans
s = Solution()
print(s.calcEquation([["a","b"],["c","d"],["a","c"]],[3.0,6.0,2.0],[["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]]))
#print(s.calcEquation([["a","b"],["e","f"],["b","e"]],[3.4,1.4,2.3],[["b","a"],["a","f"],["f","f"],["e","e"],["c","c"],["a","c"],["f","e"]]))
其他方法,拓扑排序肯定没有问题;还有人直接DFS也过了的,说明测试数据很弱:
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
def dfs(graph, start, end, visited):
if start == end and graph[start]:
return 1.0
visited.add(start)
for neigh, val in graph[start]:
if neigh in visited:
continue
tmp = dfs(graph, neigh, end, visited)
if tmp > 0:
return val * tmp
return -1.0
graph = collections.defaultdict(set)
for items, v in zip(equations, values):
x, y = items
graph[x].add((y, v))
graph[y].add((x, 1.0 / v))
res = []
for q in queries:
res.append(dfs(graph, q[0], q[1], set()))
return res