From 0dd3a73c24dddc6cd35bab770ba93e9e9ec1d001 Mon Sep 17 00:00:00 2001 From: YDZ Date: Fri, 16 Aug 2019 20:08:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20problem=20399?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../399. Evaluate Division.go | 67 +++++++++++++++++++ .../399. Evaluate Division_test.go | 44 ++++++++++++ Algorithms/0399. Evaluate Division/README.md | 42 ++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 Algorithms/0399. Evaluate Division/399. Evaluate Division.go create mode 100644 Algorithms/0399. Evaluate Division/399. Evaluate Division_test.go create mode 100755 Algorithms/0399. Evaluate Division/README.md diff --git a/Algorithms/0399. Evaluate Division/399. Evaluate Division.go b/Algorithms/0399. Evaluate Division/399. Evaluate Division.go new file mode 100644 index 00000000..44b8d058 --- /dev/null +++ b/Algorithms/0399. Evaluate Division/399. Evaluate Division.go @@ -0,0 +1,67 @@ +package leetcode + +type stringUnionFind struct { + parents map[string]string + vals map[string]float64 +} + +func (suf stringUnionFind) add(x string) { + if _, ok := suf.parents[x]; ok { + return + } + suf.parents[x] = x + suf.vals[x] = 1.0 +} + +func (suf stringUnionFind) find(x string) string { + p := "" + if v, ok := suf.parents[x]; ok { + p = v + } else { + p = x + } + if x != p { + pp := suf.find(p) + suf.vals[x] *= suf.vals[p] + suf.parents[x] = pp + } + if v, ok := suf.parents[x]; ok { + return v + } + return x +} + +func (suf stringUnionFind) union(x, y string, v float64) { + suf.add(x) + suf.add(y) + px, py := suf.find(x), suf.find(y) + suf.parents[px] = py + // x / px = vals[x] + // x / y = v + // 由上面 2 个式子就可以得出 px = v * vals[y] / vals[x] + suf.vals[px] = v * suf.vals[y] / suf.vals[x] +} + +func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 { + res, suf := make([]float64, len(queries)), stringUnionFind{parents: map[string]string{}, vals: map[string]float64{}} + for i := 0; i < len(values); i++ { + suf.union(equations[i][0], equations[i][1], values[i]) + } + for i := 0; i < len(queries); i++ { + x, y := queries[i][0], queries[i][1] + if _, ok := suf.parents[x]; ok { + if _, ok := suf.parents[y]; ok { + if suf.find(x) == suf.find(y) { + res[i] = suf.vals[x] / suf.vals[y] + } else { + res[i] = -1 + } + } else { + res[i] = -1 + } + } else { + res[i] = -1 + } + } + return res +} diff --git a/Algorithms/0399. Evaluate Division/399. Evaluate Division_test.go b/Algorithms/0399. Evaluate Division/399. Evaluate Division_test.go new file mode 100644 index 00000000..3959ce14 --- /dev/null +++ b/Algorithms/0399. Evaluate Division/399. Evaluate Division_test.go @@ -0,0 +1,44 @@ +package leetcode + +import ( + "fmt" + "testing" +) + +type question399 struct { + para399 + ans399 +} + +// para 是参数 +// one 代表第一个参数 +type para399 struct { + e [][]string + v []float64 + q [][]string +} + +// ans 是答案 +// one 代表第一个答案 +type ans399 struct { + one []float64 +} + +func Test_Problem399(t *testing.T) { + + qs := []question399{ + + question399{ + para399{[][]string{[]string{"a", "b"}, []string{"b", "c"}}, []float64{2.0, 3.0}, [][]string{[]string{"a", "c"}, []string{"b", "a"}, []string{"a", "e"}, []string{"a", "a"}, []string{"x", "x"}}}, + ans399{[]float64{6.0, 0.5, -1.0, 1.0, -1.0}}, + }, + } + + fmt.Printf("------------------------Leetcode Problem 399------------------------\n") + + for _, q := range qs { + _, p := q.ans399, q.para399 + fmt.Printf("【input】:%v 【output】:%v\n", p, calcEquation(p.e, p.v, p.q)) + } + fmt.Printf("\n\n\n") +} diff --git a/Algorithms/0399. Evaluate Division/README.md b/Algorithms/0399. Evaluate Division/README.md new file mode 100755 index 00000000..4494c7ce --- /dev/null +++ b/Algorithms/0399. Evaluate Division/README.md @@ -0,0 +1,42 @@ +# [399. Evaluate Division](https://leetcode.com/problems/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> 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. + + +## 题目大意 + +给出方程式 A / B = k, 其中 A 和 B 均为代表字符串的变量, k 是一个浮点型数字。根据已知方程式求解问题,并返回计算结果。如果结果不存在,则返回 -1.0。 + +示例 : +给定 a / b = 2.0, b / c = 3.0 +问题: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?  +返回 [6.0, 0.5, -1.0, 1.0, -1.0 ] + +输入为: vector> equations, vector& values, vector> queries(方程式,方程式结果,问题方程式), 其中 equations.size() == values.size(),即方程式的长度与方程式结果长度相等(程式与结果一一对应),并且结果值均为正数。以上为方程式的描述。 返回vector类型。 + +假设输入总是有效的。你可以假设除法运算中不会出现除数为0的情况,且不存在任何矛盾的结果。 + + +## 解题思路 + + +- 给出一些字母变量的倍数关系,问给出任意两个字母的倍数是多少。 +- 这一题可以用 DFS 或者并查集来解题。先来看看 DFS 的做法。先建图。每个字母或者字母组合可以看做成一个节点,给出的 `equations` 关系可以看成两个节点之间的有向边。每条有向边都有权值。那么问题可以转换成是否存在一条从起点节点到终点节点的路径,如果存在,输出这条路径上所有有向边权值的累乘结果。如果不存在这条路径,就返回 -1 。如果给的起点和终点不在给出的节点集里面,也输出 -1 。 +- 再来看看并查集的做法。先将每两个有倍数关系的节点做并查集 `union()` 操作。例如 A/B = 2,那么把 B 作为 `parent` 节点,`parents[A] = {B,2}`,`parents[B] = {B,1}`,B 指向自己是 1 。还有一个关系是 `B/C=3`,由于 B 已经在并查集中了,所以这个时候需要把这个关系反过来,处理成 `C/B = 1/3` ,即 `parents[C] = {B,1/3}`。这样把所有有关系的字母都 `union()` 起来。如何求任意两个字母的倍数关系呢?例如 `A/C = ?` 在并查集中查找,可以找到 `parents[C] == parents[A] == B`,那么就用 `parents[A]/parents[C] = 2/(1/3) = 6`。为什么可以这样做呢?因为 `A/B = 2`,`C/B = 1/3`,那么 `A/C = (A/B)/(C/B)` 即 `parents[A]/parents[C] = 2/(1/3) = 6`。