Equations was given A / B = k
in the format, where and was A
B
variables represented as strings, and is k
a real n Umber (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 is: 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:
The input is always valid. Assume that evaluating the queries would result in no division by zero and there are no contradiction.
Give some result division equation, and give some except the French child to query the result, according to the known division equation to find the result, no answer return-1.
The solution 1:graph,image A/b = k as a link between Node A and B, the weight from A to B are k, the reverse link is 1/k. Find a path between the nodes.
Solution 2:union Find
Solution 3:hash + DFS
Java:graph
Public double[] Calcequation (string[][] equations, double[] values, string[][] queries) {hashmap<string, Arrayl ist<string>> pairs = new hashmap<string, arraylist<string>> (); hashmap<string, arraylist<double>> valuespair = new hashmap<string, arraylist<double>> (); for (int i = 0; i < equations.length; i++) {string[] equation = equations[i]; if (!pairs.containskey (equation[0))) {Pairs.put (equation[0], New arraylist<string> ()); Valuespair.put (Equation[0], New arraylist<double> ()); } if (!pairs.containskey (equation[1])) {pairs.put (equation[1], New arraylist<string> ()); Valuespair.put (Equation[1], New arraylist<double> ()); } pairs.get (Equation[0]). Add (Equation[1]); Pairs.get (Equation[1]). Add (Equation[0]); Valuespair.get (Equation[0]). Add (Values[i]); Valuespair.get (Equation[1]). Add (1/values[i]); } double[] result = new Double[queries.length]; for (int i = 0; i < queries.length; i++) {string[] query = Queries[i]; Result[i] = DFS (query[0], query[1], pairs, Valuespair, new hashset<string> (), 1.0); if (result[i] = = 0.0) Result[i] =-1.0; } return result; } Private double Dfs (string start, String end, hashmap<string, arraylist<string>> pairs, hashmap<str ING, arraylist<double>> values, hashset<string> set, Double value) {if (Set.contains (start)) return 0.0; if (!pairs.containskey (start)) return 0.0; if (start.equals (end)) return value; Set.add (start); arraylist<string> strlist = Pairs.get (start); arraylist<double> valueList = Values.get (start); Double tmp = 0.0; for (int i = 0; i < strlist.size (); i++) {tmp = dFS (Strlist.get (i), end, pairs, values, set, Value*valuelist.get (i)); if (tmp! = 0.0) {break; }} set.remove (start); return TMP; }
Java: union Find
Class Solution {class node{String label; Double Val; Public Node (String label, double val) {this.label=label;this.val=val;} } public double[] Calcequation (string[][] equations, double[] values, string[][] queries) {map<string, node& Gt map= new hashmap<> (); for (int i=0; i<equations.length; i++) {String n= equations[i][0], d= equations[i][1]; Node n= Find (Map, N), d= find (map, D); if (! N.label.equals (D.label)) Map.put (N.label, New Node (D.label, values[i]*d.val/n.val)); } double[] res= new double[queries.length]; for (int i=0; i<res.length; i++) {res[i]=-1.0; String n=queries[i][0], d=queries[i][1]; if (!map.containskey (n) | | |!map.containskey (d)) continue; Node n= Find (Map, N), d= find (map, D); if (! N.label.equals (D.label)) continue; Res[i]=n.val/d.val; } return res; } public Node Find (Map<string, node> map, String cur) {if (!map.containskey (cur)) map.put (cur, new Node (cur, 1.0)); Node curnode= map.get (cur); Double val= 1.0; while (!map.get (cur). label.equals (cur)) {val*=map.get (cur). val; Cur=map.get (cur). label; } curnode.label=cur; Curnode.val=val; return curnode; }}
Java:
Public double[] Calcequation (string[][] equations, double[] values, string[][] query) {double[] result = new DOUBL E[query.length]; Filter unexpected words//filters out characters that have not been met set<string> words = new hashset<> (); For (string[] strs:equations) {words.add (strs[0]); Words.add (Strs[1]); } for (int i = 0; i < query.length; ++i) {string[] keys = query[i]; if (!words.contains (keys[0)) | |!words.contains (KEYS[1])) result[i] = -1.0d; else {stack<integer> Stack = new stack<> (); Result[i] = Helper (equations, values, keys, stack); }} return result; } Public double helper (string[][] equations, double[] values, string[] keys, stack<integer> Stack) {//Direct Find, key order has positive/negative/look up equations directly for (int i = 0; i < equations.length; ++i) {if (EQ Uations[i][0].equals(Keys[0]) && equations[i][1].equals (keys[1]) return values[i]; if (Equations[i][0].equals (keys[1]) && equations[i][1].equals (Keys[0])) return 1/values[i]; }//Lookup equations by other equations//indirect lookup, key order also has positive and negative for (int i = 0; i < equations.length; ++i) {if (!stack.contains (i) && keys[0].equals (Equations[i][0])) {Stack.push (i); Double temp = values[i] * Helper (equations, values, new string[]{equations[i][1], keys[1]}, Stack); if (Temp > 0) return temp; else Stack.pop (); } if (!stack.contains (i) && keys[0].equals (equations[i][1)) {Stack.push (i); Double temp = helper (equations, values, new string[]{equations[i][0], keys[1]}, Stack)/values[i]; if (Temp > 0) return temp; else Stack.pop (); }}//cannot be found, return-1 return-1.0d; }
Python: union Find
Class Solution:def calcequation (self, equations, values, queries): "" ": Type EQUATIONS:LIST[LIST[STR]] : Type Values:list[float]: type QUERIES:LIST[LIST[STR]]: rtype:list[float] "" "res = [] parent = {} # i.e. [A, b] then parent[a] = b weight = {} # i.e. A/b = 2.0, then Weight[a] = 2.0 Ufind = Unionfind (parent, weight) for I, Edge in Enumerate (equations): x1, x2 = edge[0], edge[1] val = values[i] If X1 not in the parent and X2 not in parent:parent[x1] = x2 PARENT[X2] = x2 weight[x1] = val weight[x2] = 1 elif x1 Not in Parent: PARENT[X1] = x2 weight[x1] = val elif x2 not in Parent: # WEIGHT[X1] already exists, If make X2 is X1 ' s parent. Then weight[x1] 'll be overwrite. PARENT[X2] = x1 WEIGHT[X2] = 1/val Else: Ufind.union (x1, x2, Val) for X1, x2 in Queries:if x1 not in parent or x2 Not in parent or ufind.find (x1)! = Ufind.find (x2): Res.append ( -1.0) else:factor 1 = weight[x1] Factor2 = weight[x2] Res.append (FACTOR1/FACTOR2) return res C Lass Unionfind (): Def __init__ (self, parent, weight): self.parent = Parent Self.weight = Weight def fi nd (self, vertex): if self.parent[vertex] = = Vertex:return Vertex root = Self.find (self.parent[ve Rtex]) Self.weight[vertex] *= Self.weight[self.parent[vertex] [Self.parent[vertex] = root return root Def union (Self, Vertex1, Vertex2, val): Root1 = Self.find (vertex1) Root2 = Self.find (VERTEX2) sel f.weight[root1]= SELF.WEIGHT[VERTEX2] * val/self.weight[vertex1] self.parent[root1] = Root2
Python: union Find + Path Compression + rank
def calcequation (self, equations, values, queries): "" "Time:o (e+q), Union is approx O (1) because it ' s USI Ng path compression during find. Space:o (E) "" "self.parents = {} self.weights = {} # presents it as the Val point to another graph Self.rank = {} for (W, v), Val in zip (Equations, values): If w isn't in self.parents: SELF.PARENTS[W] = w self.weights[w] = 1.0 Self.rank[w] = 1 if v not in Self.par ENTS:SELF.PARENTS[V] = v self.weights[v] = 1.0 Self.rank[v] = 1 s Elf.union (W, V, val) res = [] for query in queries:w, v = query If w isn't in Self.pare NTS or V not in Self.parents:res.append ( -1.0) Continue p1, p2 = Self.find (w), SE Lf.find (v) if p1! = P2:res.append ( -1.0) Else:res.appEnd (Self.weights[w]/self.weights[v]) return res def find (self, node): if node! = Self.parents[node] : P = self.parents[node] Self.parents[node] = Self.find (p) Self.weights[node] = Self.weig Hts[node] * Self.weights[p] return Self.parents[node] def union (self, U, V, val): P1 = self.find (u) P2 = self.find (v) if SELF.RANK[P1] > SELF.RANK[P2]: p1, p2 = p2, p1 val = 1/val V, u = u, v if p1! = p2:self.parents[p1] = P2 SELF.RANK[P2] + = Self.rank[p1] SELF.RANK[P1] = 1 Self.weights[p1] = (Self.weights[v]/self.weights[u]) * val
C++: union Find
Class Solution {public:vector<double> Calcequation (vector<pair<string, string>> equations, vector& lt;double>& values, vector<pair<string, string>> queries) {unordered_map<string, Node*> m Ap vector<double> Res; for (int i = 0; i < equations.size (); i + +) {string S1 = equations[i].first, s2 = equations[i].second; if (Map.count (s1) = = 0 && map.count (s2) = = 0) {MAP[S1] = new Node (); MAP[S2] = new Node (); MAP[S1], value = Values[i]; MAP[S2], value = 1; MAP[S1], parent = map[s2]; } else if (Map.count (s1) = = 0) {MAP[S1] = new Node (); MAP[S1], value = Map[s2], value * values[i]; MAP[S1], parent = map[s2]; } else if (map.count (s2) = = 0) {MAP[S2] = new Node (); MAP[S2], value = map[S1], value/values[i]; MAP[S2], parent = map[s1]; } else {unionnodes (map[s1], map[s2], values[i], map); }} for (auto query:queries) {if (Map.count (query.first) = = 0 | | map.count (query.second) = = 0 || Findparent (Map[query.first])! = Findparent (Map[query.second])) Res.push_back (-1); else Res.push_back (Map[query.first], Value/map[query.second], value); } return res; } private:struct Node {node* parent; Double value = 0.0; Node () {parent = this;} }; void Unionnodes (node* node1, node* node2, double num, unordered_map<string, node*>& map) {node* parent1 = Findparent (node1), *parent2 = Findparent (Node2); Double ratio = Node2, value * num/node1-value; for (Auto it = Map.begin (); It! = Map.end (); it + +) if (Findparent (IT-second) = = PARent1, it-second, value *= ratio; Parent1, parent = Parent2; } node* Findparent (node* node) {if (node, parent = = node) return node; Node-parent = findparent (node-to-parent); return node, parent; }};
C + +: Hash + DFS
Class Solution {public:vector<double> Calcequation (vector<pair<string, string>> equations, V ector<double>& values, vector<pair<string, string>> query) {Unordered_map<string,unor Dered_map<string, double>> m; vector<double> Res; for (int i = 0; i < values.size (); ++i) {M[equations[i].first].insert (Make_pair (Equations[i].second, Values[i])); if (values[i]!=0) M[equations[i].second].insert (Make_pair (equations[i].first,1/values[i])); } for (auto I:query) {unordered_set<string> s; Double tmp = check (i.first,i.second,m,s); if (TMP) Res.push_back (TMP); Else Res.push_back (-1); } return res; Double check (string up, string down, unordered_map<string,unordered_map<string, double>> & ; m, unordered_set<string> &s) { if (M[up].find (down)! = M[up].end ()) return M[up][down]; for (auto I:m[up]) {if (S.find (i.first) = = S.end ()) {S.insert (I.first); Double tmp = check (i.first,down,m,s); if (TMP) return i.second*tmp; }} return 0; }};
[Leetcode] 399. Evaluate Division to find the value of a division expression