给出方程式 A / B = k
, 其中 A
和 B
均为代表字符串的变量, k
是一个浮点型数字。根据已知方程式求解问题,并返回计算结果。如果结果不存在,则返回 -1.0
。
示例 :
给定 a / b = 2.0, b / c = 3.0
问题: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
返回 [6.0, 0.5, -1.0, 1.0, -1.0 ]
输入为: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries
(方程式,方程式结果,问题方程式), 其中 equations.size() == values.size()
,即方程式的长度与方程式结果长度相等(程式与结果一一对应),并且结果值均为正数。以上为方程式的描述。 返回vector<double>
类型。
基于上述例子,输入如下:
equations(方程式) = [ ["a", "b"], ["b", "c"] ], values(方程式结果) = [2.0, 3.0], queries(问题方程式) = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
输入总是有效的。你可以假设除法运算中不会出现除数为0的情况,且不存在任何矛盾的结果。
解题思路:
图的构建,深度优先搜索。给出的已知方程式实质上是一条边,所有方程式将构成一个图。下面给出我的构图方法:
unordered_map<string, unordered_map<string, double>> mp;
int size = equations.size(),i;
for (i = 1; i <= size; i++) {
mp[equations[i - 1].first][equations[i - 1].second] = values[i - 1];
if (values[i - 1] != 0.0) {
mp[equations[i - 1].second][equations[i - 1].first] = 1 / values[i - 1];
}
}
虽然题目中说分母不可能为0,但是分子可能为0,所以保险起见还是考虑0这种情况的存在。
构建图的过程完毕之后就是搜索问题方程式中的边是否有解。[x,y]有解得充分必要条件是:
- x的后代中有y。
- y的后代中有x。
于是很明显是关于图的DFS算法。
class Solution { public: vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries) { int size = equations.size(),i; for (i = 1; i <= size; i++) { mp[equations[i - 1].first][equations[i - 1].second] = values[i - 1]; if (values[i - 1] != 0.0) { mp[equations[i - 1].second][equations[i - 1].first] = 1 / values[i - 1]; } } size = queries.size(); vector<double> res(size, -1); for (i = 1; i <= size; i++) { res[i - 1] = solve(queries[i - 1]); visit.clear(); } return res; } double solve(pair<string, string> P) { string M = P.first, D = P.second; if (mp[M].count(D) > 0) return mp[M][D]; if (mp[D].count(M) > 0) { if (mp[D][M] == 0) return -1; else return 1 / mp[D][M]; } //试图在M的后向边中找到D。 vector<pair<string, string>> road = find(M, D); if (road.empty()) { road = find(D, M); if (road.empty()) return -1; } double res = 1; int size = road.size(); for (int i = 1; i <= size; i++) { res *= mp[road[i - 1].first][road[i - 1].second]; } return res; } vector<pair<string, string>> find(string M, string D) { visit.insert(M); unordered_map<string, double> M_next = mp[M]; if (M_next.count(D) > 0) return{ {M,D} }; unordered_map<string, double>::iterator it; for (it = M_next.begin(); it != M_next.end(); it++) { if (visit.count(it->first) == 0) { vector<pair<string, string>> res = find(it->first, D); if (!res.empty()) { res.push_back({ M,it->first }); return res; } } } return{}; } unordered_map<string, unordered_map<string, double>> mp; unordered_set<string>visit; }; |