题目描述:
Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.
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
equations = [ ["a", "b"], ["b", "c"] ],
values = [2.0, 3.0],
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
说是一道除法计算的题,其实是一道图算法的题目。将每个变量看做是一个节点,a/b=2.0,表示从a到b有一条路,这条路有一个值2.0。一个除法查询就是判断从一个节点到另外一个节点有没有通路,将经过的每条路的值相乘即得到结果,例如a/c=a/b*b/c。
首先我们根据给出的等式构建出这个图,然后通过dfs来解出每个查询的结果。利用c++的各类stl可以让编程更加方便。以下是代码:
class Solution {
private:
vector<vector<pair<int, double>>> all;
public:
double dfs(int a, int b) {
queue<int> q;
q.push(a);
//记录a除以其他点的结果
vector<double> dis(all.size(), 1.0);
//记录其他的点是否被访问过
vector<bool> isVisit(all.size(), 0);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < all[u].size(); i++) {
int x = all[u][i].first;
double y = all[u][i].second;
if (isVisit[x]==1) {
continue;
}
dis[x] = dis[u] * y;
if (x == b) {
return dis[x];
}
q.push(x);
isVisit[x] = 1;
}
}
return -1;
}
vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries) {
//convert all edges to number
map<string, int> edges;
//the whole map
//vector<vector<pair<int,double>>> all;
for (int i = 0; i < equations.size(); i++) {
string x = equations[i].first, y = equations[i].second;
if (edges.count(x) == 0) {
edges[x] = all.size();
vector<pair<int, double>> temp;
all.push_back(temp);
}
if (edges.count(y) == 0) {
edges[y] = all.size();
vector<pair<int, double>> temp;
all.push_back(temp);
}
all[edges[x]].push_back({ edges[y],values[i] });
all[edges[y]].push_back({ edges[x],1 / values[i] });
}
vector<double> results;
for (int i = 0; i < queries.size(); i++) {
string a = queries[i].first, b = queries[i].second;
//cout << a << b << endl;
if (edges.count(a) == 0 || edges.count(b) == 0) {
results.push_back(-1.0);
} else if (a == b) {
results.push_back(1.0);
}
else {
int ap = edges[a], bp = edges[b];
double re = dfs(ap, bp);
results.push_back(re);
}
}
return results;
}
};
当然这个解法并不是最优的,因为每次查询都需要做一次dfs,每次查询需要哦o(n+e)的复杂度。另外有一个解法是在一开始就将图里面可以得到的结果全都计算出来。每次查询只需要o(1)的复杂度。