# 399 Evaluate Division
input: equation, values and queries
equations = [ ["a", "b"], ["b", "c"] ],
values = [2.0, 3.0],
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]
output: the answers to input queries.
Concept:
用一個Map來存每個代數符號除以不同的數的結果。
例如:
{a={b=2.0},
b={a=0.5, c=3.0},
c={b=0.3333333333333333}}
每讀一個query就從map裡面找,看query的被除數是否可以在map裡找到除數和相除的結果。
Implementation:
- Main(): 呼叫buildMap先將map建好,再用for loop讀取每個query。
- handleQueries():
- buildMap(): 讀取所有equation,用每個equation的被除數當key輸入map,再用除數當key,value的倒數當value輸入map。
Pseudocode:
Main():
用一個map來存variable,和它所有可能的除出來的結果
例如:a/b=2.0, b/c = 3.0
a: [b:2.0]
b: [a:0.5] [c:3.0]
c: [b:0.333]
讀querie時,檢查queries[i][0]有沒有在map中,
如果有,取出key為queries[i][0]的value,看queries[i][1]有沒有在value中,
如果有,輸出,
如果沒有,如果queries[i][0]和queries[i][1]相同,輸出1.0,否則輸出-1.0。
如果沒有,輸出-1.0。
findQueries():
if(map has key numerator),
get numerator's map
if numerator's map has denominator,
return value of denominator
else
if numerator == denominator
return 1.0
else
return -1.0
else
return -1.0
buildMap():
for each row in equations,
Map<String, Double> submap = map.get(equations[i][0]);
if submap is null
submap = new HashMap<>();
submap.put(equations[i][1],values[i]);
map.put(equations[i][0],submap);
Map<String, Double> submap = map.get(equations[i][1]);
if submap is null
submap = new HashMap<>();
submap.put(equations[i][0],1/values[i]);
map.put(equations[i][1],submap);
這邊寫完後發現此時handleQueries只能處理被除數和除數關係在equation裡有定義好的情況,例如a/b, b/a, b/c, c/b...等等,但是a/c沒有定義,就算不出來。而a/c其實可以從 a/b * b/c得到。
所以handleQueries不能只用querie的nominator在map中找,要看nominator的map entry中,是否有任何entry可以到達denominator。找的時候因為a找到b時會發現a也在b的map entry中,會一直循環找到停不下來,所以需要一個Set visited,紀錄已經拜訪過的nominator,就不會不斷循環拜訪了。
Code:
public class Solution {
public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
Map<String,Map<String,Double>> map = new HashMap<>();
buildMap(equations, values, map);
double[] ans = new double[queries.length];
for(int i=0; i<queries.length; i++){
Double res = findQueries(queries[i][0], queries[i][1], map,new HashSet<>());
ans[i] = (res==null)? -1.0 : res;
}
return ans;
}
public Double findQueries(String numerator, String denominator, Map<String, Map<String, Double>> map, Set<String> visited){
String visitedKey = numerator+":"+denominator;
if(visited.contains(visitedKey))
return null;
if(!map.containsKey(numerator) || !map.containsKey(denominator))
return null;
if(numerator.equals(denominator))
return 1.0;
Map<String,Double> submap = map.get(numerator);
visited.add(visitedKey);
for(String key : submap.keySet()){
Double res = findQueries(key, denominator, map, visited);
if(res!=null){
return res * submap.get(key);
}
}
visited.remove(visitedKey);
return null;
}
public void buildMap(String[][] equations, double[] values, Map<String, Map<String, Double>> map){
for(int i=0; i<equations.length; i++){
Map<String, Double> submap = map.get(equations[i][0]);
if( submap == null){
submap = new HashMap<>();
}
submap.put(equations[i][1],values[i]);
map.put(equations[i][0],submap);
submap = map.get(equations[i][1]);
if( submap == null){
submap = new HashMap<>();
}
submap.put(equations[i][0],1/values[i]);
map.put(equations[i][1],submap);
}
}
}