Leetcode:399.除法求值

给出方程式 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]有解得充分必要条件是:

  1. x的后代中有y。
  2. y的后代中有x。

于是很明显是关于图的DFS算法。

C++代码
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;
};

猜你喜欢

转载自blog.csdn.net/qq_23523409/article/details/84799489
今日推荐