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] * 系数

 

在本问题中,

  1. 由于顶点不确定性,我们不再使用固定长度的parent。而使用动态变化的parent。这里需要增加,增加节点方法:newpoint
  2. 顶点指示为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 };

 

posted @ 2020-08-08 16:41  habibah_chang  阅读(61)  评论(0编辑  收藏  举报