20190719
Description
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.
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"] ].
Solution
Submission 1
just need to solve the multiplication problem:
cpp:
class Solution {
public:
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
unordered_map<string,double> mp; // define
for(int i=0;i<equations.size();++i){
mp[equations[i][0]+equations[i][1]]=values[i];
mp[equations[i][1]+equations[i][0]]=1/values[i];
mp[equations[i][0]+equations[i][0]]=1;
mp[equations[i][1]+equations[i][1]]=1;
}
for(int i=0;i<equations.size()-1;++i){
for(int j=i+1;j<equations.size();++j){
if(equations[i][1]==equations[j][0]){
mp[equations[i][0]+equations[j][1]] = values[i]*values[j];
mp[equations[j][1]+equations[i][0]] = 1/(values[i]*values[j]);
}
if(equations[i][1]==equations[j][1]){
mp[equations[i][0]+equations[j][0]] = values[i]/values[j];
mp[equations[j][0]+equations[i][0]] = values[j]/values[i];
}
if(equations[i][0]==equations[j][0]){
mp[equations[j][1]+equations[i][1]] = values[i]/values[j];
mp[equations[i][1]+equations[j][1]] = values[j]/values[i];
}
if(equations[i][0]==equations[j][1]){
mp[equations[j][0]+equations[i][1]] = values[i]*values[j];
mp[equations[i][1]+equations[j][0]] = 1/(values[i]*values[j]);
}
}
}
vector<double> res;
for(int i = 0;i<queries.size();++i){
if(mp.find(queries[i][0]+queries[i][1]) == mp.end())
res.push_back(-1);
else
res.push_back(mp[queries[i][0]+queries[i][1]]);
}
return res;
}
};
failed in case:
Input:
[["x1","x2"],["x2","x3"],["x3","x4"],["x4","x5"]]
[3.0,4.0,5.0,6.0]
[["x1","x5"],["x5","x2"],["x2","x4"],["x2","x2"],["x2","x9"],["x9","x9"]]
Output:
[-1.0,-1.0,20.0,1.0,-1.0,-1.0]
Expected:
[360.0,0.00833,20.0,1.0,-1.0,-1.0]
did not take continuous multiplication into consideration
Submission 2
I found it hard to solve with cpp, so I turn to python, and add continuous multiplication.
Everytime there comes a equations, check if it can multiply with the equations before.
python:
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
dic={}
n = len(values)
for i in range(n):
pair = equations[i]
f = pair[0]
t = pair[1]
if f not in dic.keys():
dic[f]={f:1}
if t not in dic.keys():
dic[t]={t:1.0}
dic[f][t] = values[i]
dic[t][f] = 1/values[i]
for tmp_k in dic[f].keys():
dic[tmp_k][t] = values[i]/dic[f][tmp_k]
dic[t][tmp_k]=dic[f][tmp_k]/values[i]
for tmp_k in dic[t].keys():
dic[f][tmp_k]=values[i]*dic[t][tmp_k]
dic[tmp_k][f]=1/(values[i]*dic[t][tmp_k])
res=[]
for i in range(len(queries)):
f = queries[i][0]
t = queries[i][1]
if f in dic.keys():
if t in dic[f].keys():
res.append(dic[f][t])
else:
res.append(-1.0)
else:
res.append(-1.0)
return res
failed at case:
Input:
[["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"]]
Output:
[0.29412,-1.0,1.0,1.0,-1.0,-1.0,0.71429]
Expected:
[0.29412,10.948,1.0,1.0,-1.0,-1.0,0.71429]
my code can not solve the multiplication order.
Submission 3
I was so depressed and turn to Discussion
, and found a elegant solution
it uses union find to build the multiplication tree, puts all the elements that can form a equation together.
python code :
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
father = {}
def findroot(key):
if father[key][0] == key:
return key
root = findroot(father[key][0])
father[key] = [root, father[key][1] * father[father[key][0]][1]]
return root
for [a, b] ,v in zip(equations, values):
if a not in father:
father[a] = [a, 1.0]
if b not in father:
father[b] = [b, 1.0]
# merge
if findroot(a) != findroot(b):
father[findroot(b)] = [findroot(a), v * (father[a][1]/father[b][1])]
ans = []
for a, b in queries:
if a not in father or b not in father or findroot(a) != findroot(b):
ans.append(-1.0)
else:
ans.append(father[b][1]/father[a][1])
return ans