399. Evaluate Division

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.

Subscribe to see which companies asked this question.


题意:输入 a / b = ?, a / c = ?.....等关系,然后求出其他关系如 b/c等,由题目给出。

容易理解,这题与图息息相关。如果 a / b = 10,可以建立a,b之间的边并赋值, 边(a,b) = 10, (b, a) = 1/10.

如果有边(a,b), (b,c),那么可以求出a/c,即 a/c = (a,b) * (b,c)。因为 a/b = (a,b), b/c = (b,c), a/c = a/b * b/c。

所以要求解 a/c的关键就是,寻找a -> c的一条路径,a/c就是路径中边的权值的乘积。

要寻找路径,可以使用DFS搜索。

代码如下:

vector<double> calcEquation(vector<pair<string, string>> equations, //记录a b关系 
                            vector<double>& values,                 //记录 a / b =  
vector<pair<string, string>> query)     //记录问题 
{
        unordered_map<string,unordered_map<string, double>> m;      //建立空图 
        vector<double> res;                                         //保存结果 
        
        //建立图 
        for (int i = 0; i < values.size(); ++i)    
        {   
            m[equations[i].first][equations[i].second] = values[i];       //建立边(a,b) 
            if(values[i]!=0)
                m[equations[i].second][equations[i].first] = 1/values[i]; //如果 a/b != 0,可以建立边(b,a) 
        }
        
        //计算,问题一个一个来计算 
        for (auto i : query)    
        {
            unordered_set<string> s;                      //每个问题使用一个string 集合来辅助DFS进行 
            double tmp = check(i.first,i.second,m,s);     //进入DFS 
            if(tmp) res.push_back(tmp);                   //答案存在 
            else res.push_back(-1);                       //答案不存在 
        }
        return res;
}


//DFS,假设求a/c 
double check(string up,    //a
        string down,  //c    两个表示问题为a/c = ? 
             unordered_map<string,unordered_map<string, double>> &m,   //图 
             unordered_set<string> &s)                                 //辅助集合 
{
        if(m[up].find(down) != m[up].end()) return m[up][down];        //如果有边(a,c),直接返回答案 
        
        //没有边(a,c),只能进行DFS搜索 
        for (auto i : m[up]) 
        {   
            if(s.find(i.first) == s.end())   //b不存在s中
            {
                s.insert(i.first);         //s加入b,表示如果这次失败,下一次走时,不要走b点,因为b走不到c 
                double tmp = check(i.first,down,m,s);   //通过b点,继续DFS 
                if(tmp) return i.second*tmp;            // 答案存在,返回 b * tmp,否则继续循环 
            }
        }
        return 0;   //答案不存在 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值