【算法】【Graph】Evaluate Division

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> equations, vector& values, vector> queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector.

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.0b指向a的边为0.5.

代码

通过Leetcode测试,速度快过75%左右的人。

class Solution {
public:
    vector<double> calcEquation(vectorstring, string>> equations, 
        vector<double>& values, vectorstring, 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无解
    }
};

你可能感兴趣的:(算法分析与设计)