活跃农民
- 积分
- 714
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2020-6-26
- 最后登录
- 1970-1-1
|
注册一亩三分地论坛,查看更多干货!
您需要 登录 才可以下载或查看附件。没有帐号?注册账号 
x
LeetCode 399: Evaluation Division
小弟我今天花了两个小时终于用Union-Find数据结构把这个题做出来了。这应该是我在刷题网提交的最长的一段code了,做出来还有点小兴奋,于是在此分享一下我的code。希望能给各位有所帮助。如有大神指点其中不足那就更好了!
- class Solution {
- public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
- Map<String, Integer> symbolMap = new HashMap<>();
- int index = 0;
- for (List<String> equation: equations) {
- for (String symbol: equation) {
- if (!symbolMap.containsKey(symbol)) {
- symbolMap.put(symbol, index++);
- }
- }
- }
-
- UF eval = new UF(symbolMap.size());
- for (int i = 0; i < values.length; i++) {
- eval.union(symbolMap.get(equations.get(i).get(0)), symbolMap.get(equations.get(i).get(1)), values[i]);
- }
-
- // System.out.println(Arrays.toString(eval.quotients));
-
- double[] res = new double[queries.size()];
- for (int i = 0; i < res.length; i++) {
- if (!symbolMap.containsKey(queries.get(i).get(0)) || !symbolMap.containsKey(queries.get(i).get(1))) {
- res[i] = -1.0;
- } else {
- res[i] = eval.find(symbolMap.get(queries.get(i).get(0)), symbolMap.get(queries.get(i).get(1)));
- }
- }
-
- return res;
- }
-
- // Use Union-Find to evaluate the quotients, with some modification to the classic implementation of UF.
- // The tricky part is to maintain the array quotients in path compression and union by rank
- private class UF {
- public int parents[], treeSizes[];
- public double quotients[]; // the quotients array is used to store the result of "node / parents[node]"
-
- public UF(int size) {
- parents = new int[size];
- treeSizes = new int[size];
- quotients = new double[size];
-
- for (int i = 0; i < size; ++i) {
- parents[i] = i;
- treeSizes[i] = 1;
- quotients[i] = 1.0;
- }
- }
-
- public void union(int node1, int node2, double q) {
- Pair<Integer, Double> r1 = getRoot(node1), r2 = getRoot(node2);
-
- if (r1.getKey() == r2.getKey()) {
- return;
- }
-
- // Note that getRoot return "q1 = node1 / root(node1)" and "q2 = node2 / root(node2)", therefore
- // q1 / q2 = (node1 / node2) * (root(node2) / root(node1))
- // since node1 / node2 is given as an input q, so we have both
- // root(node2) / root(node1) = (q1 / q2) / q
- // root(node1) / root(node2) = q * q2 / q1
- // In union by rank we choose either parents[root(node1)] = root(node2) or the other way around, so
- // we can choose to use either method depending on the situation.
- if (treeSizes[r1.getKey()] > treeSizes[r2.getKey()]) {
- parents[r2.getKey()] = r1.getKey();
- treeSizes[r1.getKey()] += treeSizes[r2.getKey()];
- quotients[r2.getKey()] = r1.getValue() / r2.getValue() / q;
- } else {
- parents[r1.getKey()] = r2.getKey();
- treeSizes[r2.getKey()] += treeSizes[r1.getKey()];
- quotients[r1.getKey()] = q * r2.getValue() / r1.getValue();
- }
- }
-
- public double find(int node1, int node2) {
- Pair<Integer, Double> r1 = getRoot(node1), r2 = getRoot(node2);
- if (r1.getKey() != r2.getKey()) {
- return -1.0;
- }
-
- // node1 / node2 = (node1 / root(node1)) / (node2 / root(node2)) * root(node2) / root(node1)
- // Note that root(node1) == root(node2) (otherwise the function returns -1.0 before this line)
- // Hence, node1 / node2 = (node1 / root(node1)) / (node2 / root(node2))
- // and these two parts are calculated by the getRoot method.
- return r1.getValue() / r2.getValue();
- }
-
- // getRoot method now need to find both the root index and the value "node / root(node)"
- private Pair<Integer, Double> getRoot(int node) {
- // Use variable q to find node / root(node)
- // node / root(node) = node/parents[node] * parents[node]/parents[parents[node]] * ...
- // = quotients[node] * quotients[parents[node]] * ...
- double q = 1.0;
- while (node != parents[node]) {
- quotients[node] = quotients[node]*quotients[parents[node]];
- parents[node] = parents[parents[node]];
-
- q *= quotients[node];
- node = parents[node];
- }
-
- return new Pair<>(node, q);
- }
- }
- }
复制代码
|
上一篇: 有向图 求“只进不出的节点下一篇: 刷题灵魂3问:刷啥题?如何刷?如何面?
|