Difficulty:Medium
Description
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<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"] ].
The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
Solution
思路
构建一个有向图(加权图),equations中的每个分母和分子都是一个节点,边则是它们相除的值。例如,a / b = 2.0
表示a
指向b
的边为2.0
,b
指向a
的边为0.5
.
代码
通过Leetcode测试,速度快过75%左右的人。
class Solution {
public:
vector<double> calcEquation(vector<pair<string, string>> equations,
vector<double>& values, vector<pair<string, string>> queries) {
vector<double> result; // 返回的结果
result.resize(queries.size());
string f, s;
// 构造有向图
for (int i = 0; i < equations.size(); ++i) {
f = equations[i].first;
s = equations[i].second;
graph[f][s] = values[i];
graph[s][f] = 1.0 / values[i];
}
double temp;
for (int i = 0; i < queries.size(); ++i) {
unordered_set<string> visited;
temp = dfs(queries[i].first, queries[i].second, visited);
result[i] = (temp == 0.0) ? -1.0 : temp;
}
return result;
}
private:
unordered_map<string, unordered_map<string, double>> graph;
double dfs(string src, string dst, unordered_set<string>& visited) {
for (pair<string, double> v : graph[src]) { // 拓展子节点
if (visited.find(v.first) == visited.end()) {
if (v.first == dst) return v.second; // 找到目标节点,返回
visited.insert(v.first);
double temp = dfs(v.first, dst, visited);
if (temp != 0) return v.second * temp; // 说明上面的dfs找到了目标,可以返回
// 否则继续拓展子节点
}
}
return 0.0; // 找不到目标,该query无解
}
};