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.

给一些有结果的除法等式,又给了一些除法式子要查询结果,根据已知除法等式求结果,没有答案的返回-1。

解法1:Graph,Image a/b = k as a link between node a and b, the weight from a to b is k, the reverse link is 1/k. Query is to find a path between two nodes.

解法2:Union Find

解法3:Hash + DFS

Java: Graph

public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
HashMap<String, ArrayList<String>> pairs = new HashMap<String, ArrayList<String>>();
HashMap<String, ArrayList<Double>> valuesPair = new HashMap<String, ArrayList<Double>>();
for (int i = 0; i < equations.length; i++) {
String[] equation = equations[i];
if (!pairs.containsKey(equation[0])) {
pairs.put(equation[0], new ArrayList<String>());
valuesPair.put(equation[0], new ArrayList<Double>());
}
if (!pairs.containsKey(equation[1])) {
pairs.put(equation[1], new ArrayList<String>());
valuesPair.put(equation[1], new ArrayList<Double>());
}
pairs.get(equation[0]).add(equation[1]);
pairs.get(equation[1]).add(equation[0]);
valuesPair.get(equation[0]).add(values[i]);
valuesPair.get(equation[1]).add(1/values[i]);
} double[] result = new double[queries.length];
for (int i = 0; i < queries.length; i++) {
String[] query = queries[i];
result[i] = dfs(query[0], query[1], pairs, valuesPair, new HashSet<String>(), 1.0);
if (result[i] == 0.0) result[i] = -1.0;
}
return result;
} private double dfs(String start, String end, HashMap<String, ArrayList<String>> pairs, HashMap<String, ArrayList<Double>> values, HashSet<String> set, double value) {
if (set.contains(start)) return 0.0;
if (!pairs.containsKey(start)) return 0.0;
if (start.equals(end)) return value;
set.add(start); ArrayList<String> strList = pairs.get(start);
ArrayList<Double> valueList = values.get(start);
double tmp = 0.0;
for (int i = 0; i < strList.size(); i++) {
tmp = dfs(strList.get(i), end, pairs, values, set, value*valueList.get(i));
if (tmp != 0.0) {
break;
}
}
set.remove(start);
return tmp;
}  

Java: Union Find

class Solution {
class Node{
String label;
double val;
public Node(String label, double val){this.label=label;this.val=val;}
}
public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
Map<String, Node> map= new HashMap<>();
for (int i=0; i<equations.length; i++){
String n= equations[i][0], d= equations[i][1];
Node N= find(map, n), D= find(map, d);
if (!N.label.equals(D.label)) map.put(N.label, new Node(D.label, values[i]*D.val/N.val));
}
double[] res= new double[queries.length];
for (int i=0; i<res.length; i++){
res[i]=-1.0;
String n=queries[i][0], d=queries[i][1];
if (!map.containsKey(n) || !map.containsKey(d)) continue;
Node N= find(map, n), D= find(map, d);
if (!N.label.equals(D.label)) continue;
res[i]=N.val/D.val;
}
return res;
}
public Node find(Map<String, Node> map, String cur){
if (!map.containsKey(cur)) map.put(cur, new Node(cur, 1.0));
Node curNode= map.get(cur);
double val= 1.0;
while (!map.get(cur).label.equals(cur)){
val*=map.get(cur).val;
cur=map.get(cur).label;
}
curNode.label=cur;
curNode.val=val;
return curNode;
}
}  

Java:

public double[] calcEquation(String[][] equations, double[] values, String[][] query) {
double[] result = new double[query.length];
// filter unexpected words
// 过滤掉没有遇见过的字符
Set<String> words = new HashSet<>();
for (String[] strs : equations) {
words.add(strs[0]);
words.add(strs[1]);
}
for (int i = 0; i < query.length; ++i) {
String[] keys = query[i];
if (!words.contains(keys[0]) || !words.contains(keys[1])) result[i] = -1.0d;
else {
Stack<Integer> stack = new Stack<>();
result[i] = helper(equations, values, keys, stack);
}
}
return result;
} public double helper(String[][] equations, double[] values, String[] keys, Stack<Integer> stack) {
// 直接查找,key的顺序有正反
// look up equations directly
for (int i = 0; i < equations.length; ++i) {
if (equations[i][0].equals(keys[0]) && equations[i][1].equals(keys[1])) return values[i];
if (equations[i][0].equals(keys[1]) && equations[i][1].equals(keys[0])) return 1 / values[i];
}
// lookup equations by other equations
// 间接查找,key的顺序也有正反
for (int i = 0; i < equations.length; ++i) {
if (!stack.contains(i) && keys[0].equals(equations[i][0])) {
stack.push(i);
double temp = values[i] * helper(equations, values, new String[]{equations[i][1], keys[1]}, stack);
if (temp > 0) return temp;
else stack.pop();
}
if (!stack.contains(i) && keys[0].equals(equations[i][1])) {
stack.push(i);
double temp = helper(equations, values, new String[]{equations[i][0], keys[1]}, stack) / values[i];
if (temp > 0) return temp;
else stack.pop();
}
}
// 查不到,返回-1
return -1.0d;
}  

Java: Union find

public double[] calcEquation(String[][] equations, double[] values, String[][] query) {

        // map string to integer
Map<String, Integer> mIdTable = new HashMap<>();
int len = 0;
for (String[] words : equations)
for (String word : words)
if (!mIdTable.containsKey(word)) mIdTable.put(word, len++); // init parent index and value
Node[] nodes = new Node[len];
for (int i = 0; i < len; ++i) nodes[i] = new Node(i); // union, you can take an example as follows
// (a/b=3)->(c/d=6)->(b/d=12)
for (int i = 0; i < equations.length; ++i) {
String[] keys = equations[i];
int k1 = mIdTable.get(keys[0]);
int k2 = mIdTable.get(keys[1]);
int groupHead1 = find(nodes, k1);
int groupHead2 = find(nodes, k2);
nodes[groupHead2].parent = groupHead1;
nodes[groupHead2].value = nodes[k1].value * values[i] / nodes[k2].value;
} // query now
double[] result = new double[query.length];
for (int i = 0; i < query.length; ++i) {
Integer k1 = mIdTable.get(query[i][0]);
Integer k2 = mIdTable.get(query[i][1]);
if (k1 == null || k2 == null) result[i] = -1d;
else {
int groupHead1 = find(nodes, k1);
int groupHead2 = find(nodes, k2);
if (groupHead1 != groupHead2) result[i] = -1d;
else result[i] = nodes[k2].value / nodes[k1].value;
}
}
return result;
} public int find(Node[] nodes, int k) {
int p = k;
while (nodes[p].parent != p) {
p = nodes[p].parent;
// compress
nodes[k].value *= nodes[p].value;
}
// compress
nodes[k].parent = p;
return p;
} private static class Node {
int parent;
double value; public Node(int index) {
this.parent = index;
this.value = 1d;
}
}  

Python: Union Find

class Solution:
def calcEquation(self, equations, values, queries):
"""
:type equations: List[List[str]]
:type values: List[float]
:type queries: List[List[str]]
:rtype: List[float]
"""
res = []
parent = {} # i.e. [a, b] then parent[a] = b
weight = {} # i.e. a / b = 2.0, then weight[a] = 2.0
ufind = UnionFind(parent, weight)
for i, edge in enumerate(equations):
x1, x2 = edge[0], edge[1]
val = values[i]
if x1 not in parent and x2 not in parent:
parent[x1] = x2
parent[x2] = x2
weight[x1] = val
weight[x2] = 1
elif x1 not in parent:
parent[x1] = x2
weight[x1] = val
elif x2 not in parent: # weight[x1] already exists, if make x2 be x1's parent. then weight[x1] will be overwrite.
parent[x2] = x1
weight[x2] = 1 / val
else:
ufind.union(x1, x2, val) for x1, x2 in queries:
if x1 not in parent or x2 not in parent or ufind.find(x1) != ufind.find(x2):
res.append(-1.0)
else:
factor1 = weight[x1]
factor2 = weight[x2]
res.append(factor1 / factor2)
return res class UnionFind():
def __init__(self, parent, weight):
self.parent = parent
self.weight = weight def find(self, vertex):
if self.parent[vertex] == vertex:
return vertex
root = self.find(self.parent[vertex])
self.weight[vertex] *= self.weight[self.parent[vertex]]
self.parent[vertex] = root
return root def union(self, vertex1, vertex2, val):
root1 = self.find(vertex1)
root2 = self.find(vertex2)
self.weight[root1]= self.weight[vertex2] * val / self.weight[vertex1]
self.parent[root1] = root2  

Python:  Union Find + Path Compression + Rank

def calcEquation(self, equations, values, queries):
"""
Time: O(E+Q) , Union is approx O(1) because it's using path compression during find.
Space: O(E)
"""
self.parents = {}
self.weights = {} # Presents it as the val point to another graph
self.rank = {}
for (w, v), val in zip(equations, values):
if w not in self.parents:
self.parents[w] = w
self.weights[w] = 1.0
self.rank[w] = 1
if v not in self.parents:
self.parents[v] = v
self.weights[v] = 1.0
self.rank[v] = 1
self.union(w, v, val)
res = []
for query in queries:
w, v = query
if w not in self.parents or v not in self.parents:
res.append(-1.0)
continue p1, p2 = self.find(w), self.find(v)
if p1 != p2:
res.append(-1.0)
else:
res.append(self.weights[w] / self.weights[v])
return res def find(self, node):
if node != self.parents[node]:
p = self.parents[node]
self.parents[node] = self.find(p)
self.weights[node] = self.weights[node] * self.weights[p]
return self.parents[node] def union(self, u, v, val):
p1 = self.find(u)
p2 = self.find(v)
if self.rank[p1] > self.rank[p2]:
p1, p2 = p2, p1
val = 1 / val
v, u = u, v
if p1 != p2:
self.parents[p1] = p2
self.rank[p2] += self.rank[p1]
self.rank[p1] = 1
self.weights[p1] = (self.weights[v] / self.weights[u] ) * val 

C++:  Union Find

class Solution {
public:
vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries) {
unordered_map<string, Node*> map;
vector<double> res;
for (int i = 0; i < equations.size(); i ++) {
string s1 = equations[i].first, s2 = equations[i].second;
if (map.count(s1) == 0 && map.count(s2) == 0) {
map[s1] = new Node();
map[s2] = new Node();
map[s1] -> value = values[i];
map[s2] -> value = 1;
map[s1] -> parent = map[s2];
} else if (map.count(s1) == 0) {
map[s1] = new Node();
map[s1] -> value = map[s2] -> value * values[i];
map[s1] -> parent = map[s2];
} else if (map.count(s2) == 0) {
map[s2] = new Node();
map[s2] -> value = map[s1] -> value / values[i];
map[s2] -> parent = map[s1];
} else {
unionNodes(map[s1], map[s2], values[i], map);
}
} for (auto query : queries) {
if (map.count(query.first) == 0 || map.count(query.second) == 0 || findParent(map[query.first]) != findParent(map[query.second]))
res.push_back(-1);
else
res.push_back(map[query.first] -> value / map[query.second] -> value);
}
return res;
} private:
struct Node {
Node* parent;
double value = 0.0;
Node() {parent = this;}
}; void unionNodes(Node* node1, Node* node2, double num, unordered_map<string, Node*>& map) {
Node* parent1 = findParent(node1), *parent2 = findParent(node2);
double ratio = node2 -> value * num / node1 -> value;
for (auto it = map.begin(); it != map.end(); it ++)
if (findParent(it -> second) == parent1)
it -> second -> value *= ratio;
parent1 -> parent = parent2;
} Node* findParent(Node* node) {
if (node -> parent == node)
return node;
node -> parent = findParent(node -> parent);
return node -> parent;
}
};

C++: Hash + DFS  

class Solution {
public:
vector<double> calcEquation(vector<pair<string, string>> equations,
vector<double>& values, 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].insert(make_pair(equations[i].second,values[i]));
if(values[i]!=0)
m[equations[i].second].insert(make_pair(equations[i].first,1/values[i]));
} for (auto i : query)
{
unordered_set<string> s;
double tmp = check(i.first,i.second,m,s);
if(tmp) res.push_back(tmp);
else res.push_back(-1);
}
return res;
} double check(string up, string down,
unordered_map<string,unordered_map<string, double>> &m,
unordered_set<string> &s)
{
if(m[up].find(down) != m[up].end()) return m[up][down];
for (auto i : m[up])
{
if(s.find(i.first) == s.end())
{
s.insert(i.first);
double tmp = check(i.first,down,m,s);
if(tmp) return i.second*tmp;
}
}
return 0;
}
};

  

All LeetCode Questions List 题目汇总

[LeetCode] 399. Evaluate Division 求除法表达式的值的更多相关文章

  1. [LeetCode] Evaluate Division 求除法表达式的值

    Equations are given in the format A / B = k, where A and B are variables represented as strings, and ...

  2. LN : leetcode 399 Evaluate Division

    lc 399 Evaluate Division 399 Evaluate Division Equations are given in the format A / B = k, where A ...

  3. [leetcode] 399. Evaluate Division

    我是链接 看到这道题,2个点和一个权值,然后想到图,但是leetcode就是这样,没给数据范围,感觉写起来很费劲,然后就开始用图来做,添加边的时候,注意正向边和反向变,然后查询的时候,先判断2个点是否 ...

  4. pat02-线性结构3. 求前缀表达式的值(25)

    02-线性结构3. 求前缀表达式的值(25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 算术表达式有前缀表示法.中缀表示法和后缀表示法 ...

  5. PTA笔记 堆栈模拟队列+求前缀表达式的值

    基础实验 3-2.5 堆栈模拟队列 (25 分) 设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q. 所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操作函数: int IsFull(Sta ...

  6. 信息竞赛进阶指南--递归法求中缀表达式的值,O(n^2)(模板)

    // 递归法求中缀表达式的值,O(n^2) int calc(int l, int r) { // 寻找未被任何括号包含的最后一个加减号 for (int i = r, j = 0; i >= ...

  7. [Leetcode Week3]Evaluate Division

    Evaluate Division题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/evaluate-division/description/ Desc ...

  8. 【Zhejiang University PATest】02-3. 求前缀表达式的值

    算术表达式有前缀表示法.中缀表示法和后缀表示法等形式.前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4.请设计程序计算 ...

  9. openjduge 求简单表达式的值

    表达式求值 总时间限制:  10000ms  单个测试点时间限制:  1000ms  内存限制:  131072kB 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. 输入 输入仅有一行 ...

随机推荐

  1. 微信小程序~扫码

    为了让用户减少输入,我们可以把复杂的信息编码成一个二维码,利用宿主环境wx.scanCode这个API调起微信扫一扫,用户扫码之后,wx.scanCode的success回调会收到这个二维码所对应的字 ...

  2. 微信小程序~Flex布局

    有一点需要注意的是,你的小程序要求兼容到iOS8以下版本,需要开启样式自动补全.开启样式自动补全,在“设置”—“项目设置”—勾选“上传代码时样式自动补全”.

  3. string长度问题

    原文地址: https://toutiao.io/shares/2029578/url String是Java中很重要的一个数据类型,除了基本数据类型以外,String是被使用的最广泛的了,但是,关于 ...

  4. [bzoj 4176] Lucas的数论 (杜教筛 + 莫比乌斯反演)

    题面 设d(x)d(x)d(x)为xxx的约数个数,给定NNN,求 ∑i=1N∑j=1Nd(ij)\sum^{N}_{i=1}\sum^{N}_{j=1} d(ij)i=1∑N​j=1∑N​d(ij) ...

  5. 中断点异常 STATUS_BREAKPOINT(0x80000003)

    简介 STATUS_BREAKPOINT,值为0x80000003,称为中断指令异常,表示在系统未附加内核调试器时遇到断点或断言. 触发条件 通常中断指令异常可以在以下条件下触发: 硬代码中断请求,如 ...

  6. 使用go-mysql-server 开发自己的mysql server

    go-mysql-server是一个golang 的mysql server 协议实现包,使用此工具我们可以用来做好多方便的东西 基于mysql 协议暴露自己的本地文件为sql 查询 基于mysql ...

  7. 洛谷 题解 P2731 【骑马修栅栏 Riding the Fences】

    简单的开始 完美の开始 这里数组什么的用来干什么后面标注的清楚了 #include<iostream> #include<cstdio> #include<cmath&g ...

  8. Sybase数据库连接配置

    简介 1984年,Mark B. Hiffman和Robert Epstern创建了Sybase公司,并在1987年推出了Sybase数据库产品.SYBASE主要有三种版本,一是UNIX操作系统下运行 ...

  9. 深度clone和浅clone

    首先等你有空的时候可以看这篇,要用可以看我这篇 https://www.cnblogs.com/echolun/p/7889848.html 1.有一点需要明确的是 深拷贝只是针对引用数据类型来说的, ...

  10. Node.js之删除文件夹(含递归删除)

    应用场景:比如像Eclipse这样的IDE,右击项目,出现选项,点击选项中的删除,就可以删除这个项目及其下的子目录包含文件(使用electron开发的桌面端项目多少都会用到). 核心代码如下: /** ...