【leetcode】399. 除法求值( Evaluate Division )
给出方程式 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 ]
输入为:
其中 equations.size() == values.size(),即方程式的长度与方程式结果长度相等(程式与结果一一对应),并且结果值均为正数。以上为方程式的描述。 返回vector
基于上述例子,输入如下:
equations(方程式) = [ ["a", "b"], ["b", "c"] ],
values(方程式结果) = [2.0, 3.0],
queries(问题方程式) = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
输入总是有效的。你可以假设除法运算中不会出现除数为0的情况,且不存在任何矛盾的结果。
思路
构建带权值边的并查集,对于每个方程式有两种情况
例如,对于题目示例:
注意:
test case:
[[“a”,“b”],[“b”,“c”]]
[2.0,3.0]
[[“a”,“c”],[“b”,“a”],[“a”,“e”],[“a”,“a”],[“x”,“x”]]
[[“a”,“b”],[“b”,“c”],[“bc”,“cd”]]
[1.5,2.5,5.0]
[[“a”,“c”],[“c”,“b”],[“bc”,“cd”],[“cd”,“bc”]]
代码:
class Solution {
public:
int count;
unordered_map<string, string> parents; // 存储当前结点的父母
unordered_map<string, double> weights; // 存储 当前结点值/父母值 的结果
// 返回root以及从a/root的值
pair<string ,double> MyFind(string a){
if(parents.find(a) == parents.end())
return {
"", -1.0};
double result = 1.0;
while(a != parents[a]){
result *= weights[a]; // result *= a/parent;
// 路径压缩后还需要更新weights,这里偷懒就不路径压缩了
a = parents[a];
}
return {
a, result}; // 返回a的根节点,和a/root的结果
}
// a_b表示a除以b的结果
void MyUnion(string a, string b, double a_b){
pair<string, double> p1 = MyFind(a);
pair<string, double> p2 = MyFind(b);
if("" == p1.first || "" == p2.first) return;
if(p1.first == p2.first) return;
parents[p1.first] = p2.first;
weights[p1.first] = 1/p1.second * a_b * p2.second; // 更新权重
count--;
}
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
// 并
for(int i=0; i<equations.size(); ++i){
string a = equations[i][0];
string b = equations[i][1];
// 并查集初始化
if(parents.find(a) == parents.end()){
count++;
parents[a] = a;
weights[a] = 1.0;
}
if(parents.find(b) == parents.end()){
count++;
parents[b] = b;
weights[b] = 1.0;
}
// 并操作
MyUnion(a, b, values[i]);
}
// 查
vector<double> result;
for(auto &q : queries){
string a = q[0];
string b = q[1];
pair<string, double> p1 = MyFind(a); // p1.second = a/p1
pair<string, double> p2 = MyFind(b); // p2.second = b/p2
if(p1.first != p2.first || "" == p1.first || "" == p2.first){
result.push_back(-1.0);
}
else{
result.push_back(p1.second/p2.second); // a/b = (a/p1) / (b/p2);
}
}
return result;
}
};