399. Evaluate Division
阿新 • • 發佈:2020-08-08
問題:
給定 一組【被除數,除數,商】的陣列,根據已知的等式關係,
求要求的一組【被除數,除數】的商。
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 };