399. Evaluate Division
问题:
给定 一组【被除数,除数,商】的数组,根据已知的等式关系,
求要求的一组【被除数,除数】的商。
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: equations = [ ["a", "b"], ["b", "c"] ], values = [2.0, 3.0], queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
解法:并查集(Disjoint Set)
根据给定的【被除数,除数,商】,可以建立【被除数,除数】之间的关系(系数为【商】)
则所有【被除数,除数】对,可以看作两个顶点的连接。(【商】为两点连接的系数)
最后所求为,给定两个点是否有连接,没有的话,返回-1,否则返回两点之间的系数【商】。
因此,我们可在原来基础的Disjoint Set中parent的关系基础上,增加一个变量,来指示二点之间的关系系数【商】
vector<pair<int, double>> parent;
- parent[i].first:顶点 i 的父节点
- parent[i].second:顶点 i 与其父节点的关系系数
-> 顶点 i = parent[i] * 系数
在本问题中,
- 由于顶点不确定性,我们不再使用固定长度的parent。而使用动态变化的parent。这里需要增加,增加节点方法:newpoint
- 顶点指示为string类型,因此需要增加映射,unordered_map<string, int> pos;
综上,我们对本问题经过适用改善的Disjoint Set类变为:
1 class DisjointSet { 2 public: 3 DisjointSet() {} 4 void newpoint() { 5 parent.push_back(make_pair(parent.size(), 1.0)); 6 rank.push_back(0); 7 } 8 pair<int, double> find(int i) { 9 if(parent[i].first != i){ 10 pair<int, double> pa = find(parent[i].first); 11 parent[i].first = pa.first; 12 parent[i].second *= pa.second; 13 } 14 return parent[i]; 15 } 16 bool merge(int x, int y, double val) {//x=y*val 17 pair<int, double> x_root = find(x); 18 pair<int, double> y_root = find(y); 19 if(x_root.first == y_root.first) return false; 20 if(rank[x_root.first] < rank[y_root.first]) { 21 parent[x_root.first].first = y_root.first; 22 parent[x_root.first].second = y_root.second * val; 23 } else if(rank[y_root.first] < rank[x_root.first]) { 24 parent[y_root.first].first = x_root.first; 25 parent[y_root.first].second = x_root.second / val ; 26 } else { 27 parent[x_root.first].first = y_root.first; 28 parent[x_root.first].second = y_root.second * val; 29 rank[y_root.first] ++; 30 } 31 return true; 32 } 33 double getdivideval(int x, int y) { 34 pair<int, double> x_root = find(x); 35 pair<int, double> y_root = find(y); 36 if(x_root.first == y_root.first) return x_root.second/y_root.second; 37 else return -1.0; 38 } 39 private: 40 vector<pair<int, double>> parent; 41 vector<int> rank; 42 };
本问题的解决
代码参考:
1 class Solution { 2 public: 3 vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) { 4 vector<double> res; 5 unordered_map<string, int> pos; 6 DisjointSet DS; 7 for(int i=0; i<values.size(); i++) { 8 string a = equations[i][0]; 9 string b = equations[i][1]; 10 double val = values[i]; 11 if(pos.count(a)==0) { 12 pos[a] = pos.size(); 13 DS.newpoint(); 14 } 15 if(pos.count(b)==0) { 16 pos[b] = pos.size(); 17 DS.newpoint(); 18 } 19 DS.merge(pos[a],pos[b],val); 20 } 21 for(vector<string> q:queries) { 22 if(pos.count(q[0]) == 0 || pos.count(q[1]) == 0) { 23 res.push_back(-1.0); 24 } else { 25 res.push_back(DS.getdivideval(pos[q[0]], pos[q[1]])); 26 } 27 } 28 return res; 29 } 30 };