Evaluate Division

`## Evaluate Division update Jul,31 2017 22:43

LeetCodearrow-up-right

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.

Basic Idea:

思路就是有题目所给信息构造一个 graph。例如:对于 a / b = 2,则新建 node a,neighbor b,weight = 2, node b,neighbor a,weight = 1/2。然后我们对每个 query,对 graph 做 dfs,从 query[0] 找到 query[1],沿途的 edge weight 累乘的积就是结果。

Java Code:

Python Code:

update 2018-05-24 00:21:10

更新 C++ BFS Solution:

使用BFS可以更加节省时间,也不需要提前显示建图,但是需要将所有equation的两项互换位置后添加进equations中用来处理倒数的问题。另外query两项相同的情况也要另外处理。

另外,为了记录每个节点的累乘数值,需要建一个inner class(or struct);

C++ DFS Solution:

C++ 版本的建图的解法,和之前Java的实现相比有一些优化:

  1. 图的形式不必是两层HashMap,外层其实可以直接用vector(list);

  2. 在dfs的过程中,只要出现一次 childRet 不为 -1,就可以终止余下部分的dfs,这一步剪枝可以减少很多工作;

update 2018-06-24 20:48:22

Update,C++ BFS Solution

这次的实现中不再使用自定义struct储存node信息,而是用 pair 存储。Node(Vertex)其实只需要两个field:(上一个分母和当前的value)。

update Nov 25th, 2018

Update: Java Floyd Solution

利用Floyd算法,先求出每一对variable之间的商,再处理query。时间复杂度为 O(V^3).

Update: Optimal Solution: Union-Find

利用并查集的思路,我们可以把输入equation转换成child/parent=val 的形式,然后尽可能统一parent。例如输入a/b=2, b/c=3,我们如果令b为parent,则有 parent[a]={b,2}, parent[c]={b,1/3}, 这样计算a/c 的时候,就可以有 a/c=(a/b) / (c/b) = 2 / (1/3) = 6。 具体地,并查集的形式可以是 Map<String, pair<String, Integer>>。另外需要注意在find的时候做path compression,在union的时候分类考虑。

Java Code: