题目大意:给你一些含有变量名的分式的值,让你计算另外一些分式的值,如果不能计算返回-1。
Problem:
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:
1 2 3 |
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.
Solution 1: DFS
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
// Author: Huahua // Runtime: 3 ms class Solution { public: vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries) { // g[A][B] = k -> A / B = k unordered_map<string, unordered_map<string, double>> g; for (int i = 0; i < equations.size(); ++i) { const string& A = equations[i].first; const string& B = equations[i].second; const double k = values[i]; g[A][B] = k; g[B][A] = 1.0 / k; } vector<double> ans; for (const auto& pair : queries) { const string& X = pair.first; const string& Y = pair.second; if (!g.count(X) || !g.count(Y)) { ans.push_back(-1.0); continue; } unordered_set<string> visited; ans.push_back(divide(X, Y, g, visited)); } return ans; } private: // get result of A / B double divide(const string& A, const string& B, unordered_map<string, unordered_map<string, double>>& g, unordered_set<string>& visited) { if (A == B) return 1.0; visited.insert(A); for (const auto& pair : g[A]) { const string& C = pair.first; if (visited.count(C)) continue; double d = divide(C, B, g, visited); // d = C / B // A / B = C / B * A / C if (d > 0) return d * g[A][C]; } return -1.0; } }; |
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// Updated: 2020/9/27 // Author: Huahua // Running time: 1 ms class Solution { private Map<String, HashMap<String, Double>> g = new HashMap<>(); public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) { for (int i = 0; i < equations.size(); ++i) { String x = equations.get(i).get(0); String y = equations.get(i).get(1); double k = values[i]; g.computeIfAbsent(x, l -> new HashMap<String, Double>()).put(y, k); g.computeIfAbsent(y, l -> new HashMap<String, Double>()).put(x, 1.0 / k); } double[] ans = new double[queries.size()]; for (int i = 0; i < queries.size(); ++i) { String x = queries.get(i).get(0); String y = queries.get(i).get(1); if (!g.containsKey(x) || !g.containsKey(y)) { ans[i] = -1.0; } else { ans[i] = divide(x, y, new HashSet<String>()); } } return ans; } private double divide(String x, String y, Set<String> visited) { if (x.equals(y)) return 1.0; visited.add(x); if (!g.containsKey(x)) return -1.0; for (String n : g.get(x).keySet()) { if (visited.contains(n)) continue; visited.add(n); double d = divide(n, y, visited); if (d > 0) return d * g.get(x).get(n); } return -1.0; } } |
Python3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
""" Author: Huahua Running time: 32 ms (beats 100%) """ class Solution: def calcEquation(self, equations, values, queries): def divide(x, y, visited): if x == y: return 1.0 visited.add(x) for n in g[x]: if n in visited: continue visited.add(n) d = divide(n, y, visited) if d > 0: return d * g[x][n] return -1.0 g = collections.defaultdict(dict) for (x, y), v in zip(equations, values): g[x][y] = v g[y][x] = 1.0 / v ans = [divide(x, y, set()) if x in g and y in g else -1 for x, y in queries] return ans |
Solution 2: Union Find
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// Author: Huahua // Runtime: 3 ms class Solution { public: vector<double> calcEquation(const vector<pair<string, string>>& equations, vector<double>& values, const vector<pair<string, string>>& queries) { // parents["A"] = {"B", 2.0} -> A = 2.0 * B // parents["B"] = {"C", 3.0} -> B = 3.0 * C unordered_map<string, pair<string, double>> parents; for (int i = 0; i < equations.size(); ++i) { const string& A = equations[i].first; const string& B = equations[i].second; const double k = values[i]; // Neighter is in the forrest if (!parents.count(A) && !parents.count(B)) { parents[A] = {B, k}; parents[B] = {B, 1.0}; } else if (!parents.count(A)) { parents[A] = {B, k}; } else if (!parents.count(B)) { parents[B] = {A, 1.0 / k}; } else { auto& rA = find(A, parents); auto& rB = find(B, parents); parents[rA.first] = {rB.first, k / rA.second * rB.second}; } } vector<double> ans; for (const auto& pair : queries) { const string& X = pair.first; const string& Y = pair.second; if (!parents.count(X) || !parents.count(Y)) { ans.push_back(-1.0); continue; } auto& rX = find(X, parents); // {rX, X / rX} auto& rY = find(Y, parents); // {rY, Y / rY} if (rX.first != rY.first) ans.push_back(-1.0); else // X / Y = (X / rX / (Y / rY)) ans.push_back(rX.second / rY.second); } return ans; } private: pair<string, double>& find(const string& C, unordered_map<string, pair<string, double>>& parents) { if (C != parents[C].first) { const auto& p = find(parents[C].first, parents); parents[C].first = p.first; parents[C].second *= p.second; } return parents[C]; } }; |
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
// Updated: 9/27/2020 // Author: Huahua // Running time: 3 ms class Solution { class Node { public String parent; public double ratio; public Node(String parent, double ratio) { this.parent = parent; this.ratio = ratio; } } class UnionFindSet { private Map<String, Node> parents = new HashMap<>(); public Node find(String s) { if (!parents.containsKey(s)) return null; Node n = parents.get(s); if (!n.parent.equals(s)) { Node p = find(n.parent); n.parent = p.parent; n.ratio *= p.ratio; } return n; } public void union(String A, String B, double ratio) { boolean hasA = parents.containsKey(A); boolean hasB = parents.containsKey(B); if (!hasA && !hasB) { parents.put(A, new Node(B, ratio)); parents.put(B, new Node(B, 1.0)); } else if (!hasA) { parents.put(A, new Node(B, ratio)); } else if (!hasB) { parents.put(B, new Node(A, 1.0 / ratio)); } else { Node rA = find(A); Node rB = find(B); parents.put(rA.parent, new Node(rB.parent, ratio / rA.ratio * rB.ratio)); } } } public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) { UnionFindSet u = new UnionFindSet(); for (int i = 0; i < equations.size(); ++i) u.union(equations.get(i).get(0), equations.get(i).get(1), values[i]); double[] ans = new double[queries.size()]; for (int i = 0; i < queries.size(); ++i) { Node rx = u.find(queries.get(i).get(0)); Node ry = u.find(queries.get(i).get(1)); if (rx == null || ry == null || !rx.parent.equals(ry.parent)) ans[i] = -1.0; else ans[i] = rx.ratio / ry.ratio; } return ans; } } |
Python3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
""" Author: Huahua Running time: 32 ms (beats 100%) """ class Solution: def calcEquation(self, equations, values, queries): def find(x): if x != U[x][0]: px, pv = find(U[x][0]) U[x] = (px, U[x][1] * pv) return U[x] def divide(x, y): rx, vx = find(x) ry, vy = find(y) if rx != ry: return -1.0 return vx / vy U = {} for (x, y), v in zip(equations, values): if x not in U and y not in U: U[x] = (y, v) U[y] = (y, 1.0) elif x not in U: U[x] = (y, v) elif y not in U: U[y] = (x, 1.0 / v) else: rx, vx = find(x) ry, vy = find(y) U[rx] = (ry, v / vx * vy) ans = [divide(x, y) if x in U and y in U else -1 for x, y in queries] return ans |
Related Problems:
请尊重作者的劳动成果,转载请注明出处!花花保留对文章/视频的所有权利。
如果您喜欢这篇文章/视频,欢迎您捐赠花花。
If you like my articles / videos, donations are welcome.
Be First to Comment