并查集
union_nodes函数中ratio的推导
n
1
n_1
n1与
n
2
n_2
n2是不同树上的两个节点的值,合并后修改
n
1
n_1
n1为
n
1
′
n'_1
n1′,使得比值
n
1
′
/
n
2
=
n
u
m
n'_1/n_2=num
n1′/n2=num,即
n
1
′
=
n
u
m
×
n
2
n'_1=num \times n_2
n1′=num×n2
r
a
t
i
o
=
n
1
′
/
n
1
=
n
u
m
×
n
2
/
n
1
ratio=n'_1/n_1=num \times n_2/n_1
ratio=n1′/n1=num×n2/n1
class Solution {
//每个节点(除根节点外)都有一个父节点
//因此整个问题的数据结构就是由多棵树(不是二叉树)组成的森林
struct Node{
double val;
Node* parent;
Node():parent(nullptr){}
Node(double value):val(value),parent(nullptr){}
};
//找到node节点的根节点
Node* find_parent(Node* node){
while(node->parent)
node = node->parent;
return node;
}
//将n1与n2所在的树合并为一棵树
//将n2所在树的根节点p2指定为n1所在树的根节点p1的父节点
void union_nodes(Node* n1, Node* n2, double num, const unordered_map<string,Node*> &hash){
Node *p1 = find_parent(n1), *p2 = find_parent(n2);
double ratio = n2->val * num / n1->val;//此处为n1所在树的所有节点都要乘的系数
for(auto node : hash)
if(find_parent(node.second) == p1)
node.second->val *= ratio;
p1->parent = p2;
}
public:
vector<double> calcEquation(vector<vector<string>>& equations,
vector<double>& values, vector<vector<string>>& queries) {
unordered_map<string,Node*> hash;//存放已经存在的节点
vector<double> res;
//建立森林
for(int i=0;i<equations.size();++i){
string str1 = equations[i][0];//第一个节点
string str2 = equations[i][1];//第二个节点
double value = values[i];//比值node1/node2=value,即node1= node2 * value;
//当2个节点都不存在时
if(hash.find(str1) == hash.end() && hash.find(str2) == hash.end()){
//由于都不存在,索性将第一个节点的值设为value,第二个节点设为1,这样两者的比值也符合设定
hash[str1] = new Node(value);
hash[str2] = new Node(1);
hash[str2]->parent = hash[str1];
//只有第一个节点存在
}else if(hash.find(str1) == hash.end()){
//node1 = node2 * value;
hash[str1] = new Node(hash[str2]->val*value);
hash[str1]->parent = hash[str2];
//只有第二个节点存在
}else if(hash.find(str2) == hash.end()){
//node1 = node2 * value,即node2 = node1 / value;
hash[str2] = new Node(hash[str1]->val/value);
hash[str2]->parent = hash[str1];
//两个节点都存在
}else{
//两个节点都存在,则合并两棵树
union_nodes(hash[str1],hash[str2],value,hash);
}
}
for(auto query:queries)
//如果两个节点都存在且在同一棵树上,则直接求值;否则设为-1.0
if(hash.find(query[0])!=hash.end()
&& hash.find(query[1])!=hash.end()
&& find_parent(hash[query[0]]) == find_parent(hash[query[1]]))
res.push_back(hash[query[0]]->val / hash[query[1]]->val);
else
res.push_back(-1.0);
return res;
}
};