Evaluate Division(LeetCode 339)

来源:互联网 发布:淘宝复制链接打不开啊 编辑:程序博客网 时间:2024/06/05 11:51

题目

  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.

题目大意

题目大概是说给若干个形如a/b=k的等式,其中a,b是字符串,k是double类型的常数,然后再给你几个同样形如a/b的式子,让你根据之前的等式求出这些式子的值,例如a/b=2.0,b/c=3.0,现在求a/c,值为6.0。
还有a/x,因为x这个字符串之前没给出,所以是不合法的值,定义为-1.0。这里还要注意一点,所有等式的值均为正值。

分析

这道题因为牵扯到很多变量之间的关系,那么考虑下我们学过什么模型或者算法里面牵扯到很多变量之间的关系?嗯,如果这里把每一个变量都看成是一个结点,k值看做是边的权值,那么是不是很像数据结构中的图论,当然这里是有向图,而且是带环的,毕竟自己除自己也是有意义的,值为1.0。上面的example对应的图画出来差不多就像下面这个样子:
这里写图片描述
每条边的权值都是它的弧尾/弧头的值,例如a/b=2,b/a=1.0/2.0。
    那么接下来就简单了,整个问题也就转换为了求从顶点i到
顶点j的路径的权值之积就好了,例如求c/a,那么只要c->b->a这条路径上的权值相乘就好了,也就是0.3333*2.0。那么现在只要找到c->a的路径就可以得到答案了。也就是对这个图做个dfs的事。

    不过这里要注意一点,如果dfs用递归实现,会提示running error,我放到vs下调试发现是stack over flow也就是递归导致内存溢出了,所以只好考虑用dfs的非递归的版本去实现。

    好了,下面先给出代码,然后再分析代码吧

class Solution {public:    vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries) {        unordered_map<string, int> symbol;        int index = 0;        vector<double> res;        for (int i = 0; i<equations.size(); i++) {            if (symbol.find(equations[i].first) == symbol.end()) {                symbol[equations[i].first] = index++;            }            if (symbol.find(equations[i].second) == symbol.end()) {                symbol[equations[i].second] = index++;            }        }        vector<vector<double>> graph;/*define the graph*/                                     /*init the graph*/        for (int i = 0; i<index; i++) {            graph.emplace_back(vector<double>());            for (int j = 0; j<index; j++) {                if (i == j)                    graph[i].emplace_back(1.0);                else                    graph[i].emplace_back(-1.0);            }        }        /*create all edges*/        for (int i = 0; i<equations.size(); i++) {            int a = symbol[equations[i].first];            int b = symbol[equations[i].second];            graph[a][b] = values[i];            graph[b][a] = 1.0 / values[i];        }        /*get the result*/        for (int i = 0; i<queries.size(); i++) {            if (symbol.find(queries[i].first) == symbol.end() || symbol.find(queries[i].second) == symbol.end())                res.emplace_back(-1.0);            else                res.emplace_back(getRes(symbol[queries[i].first], symbol[queries[i].second], graph));        }        return res;    }private:    double getRes(int start, int end, vector<vector<double>> graph) {/*get the weight from start to end*/        return dfs(start,end,graph);    }    double dfs(int start ,int end, vector<vector<double>> graph) {        if (start == end)            return 1.0;        double temp = 1.0;        double priortemp=1.0;        vector<bool> visited;        for (int i = 0; i < graph.size(); i++)            visited.emplace_back(false);        stack<int> m_stack;        m_stack.push(start);        visited[start] = true;        while (!m_stack.empty()) {            int tmp = m_stack.top();            int i = 0;            for (i = 0; i < graph.size(); i++) {                if (visited[i]|| graph[tmp][i] == -1.0)                    continue;                m_stack.push(i);                visited[i] = true;                priortemp=temp;                temp *= graph[tmp][i];                if (i == end) {                    return temp;                }                break;            }            if (i == graph.size()){/*back to the prior state*/                m_stack.pop();                temp=priortemp;            }        }        return -1.0;    }};

calcEquation()先从这个函数开始吧。首先我懒的用邻接表去存储图,所以就想用邻接矩阵去存,但是这题目给了一大堆字符串,肯定不方便用下标去表示,于是我想到先用unordered_map先把这些字符串和下标绑定,接着直接用这些下标用vector建立一个邻接矩阵。之后就是对题目给定的表达式逐个求值了。再来讲讲dfs函数,这是一个简单的dfs非递归实现,但是要注意,我使用了一个priortemp变量来记录回溯时要用的值。嗯,差不多就这样吧