题目链接
思路
- 这个题可以看作一个寻找路径的问题~
- 我们把所有出现的数字看作一个结点 那么这道题算除法就是让我们找到两个结点间的路径积是多少 而且有向图的边是有权重的,因此可以看作一个有向网~
- 注意两个结点 如果E(a,b) = m 则E(b,a) = 1/m
- 还有一点在于 E(a,b)表示a/b,如果我们要找a/c 我们可以找到a/b,然后再找到b/c,这两个结果应该做乘法,所以求的是路径积
- 最后是如何表示图?我们可以用一个Map来表示结点和边的映射,具体的value还是一个Map,是临近节点和权重的映射
Map<String,Map<String,Double>> graph
- 此题为了防止重复搜索,仍然需要visited集合 一定要仔细阅读dfs代码,这里更像是回溯法
- 这样处理visited是因为,如果某一步我从[1]搜寻到[234],然后又通过[2]搜索到了[5],如果不在递归函数结束时清除[5]的visited状态,那么我们便无法通过[34]还有[1]再搜索到5,因此会漏掉情况!!
class Solution {
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
Map<String,Map<String,Double>> graph = new HashMap<>();
for(int i = 0 ; i < equations.size() ; i++){
List<String> equation = equations.get(i);
String s1 = equation.get(0) , s2 = equation.get(1);
Map<String,Double> map1 = graph.getOrDefault(s1,new HashMap<>()),
map2 = graph.getOrDefault(s2,new HashMap<>());
map1.put(s2,values[i]);
map2.put(s1,1/values[i]);
graph.put(s1,map1);
graph.put(s2,map2);
}
double[] result = new double[queries.size()];
Set<String> visited = new HashSet<>();
for(int i = 0 ; i < queries.size() ; i++){
List<String> query = queries.get(i);
result[i] = dfs(graph,query.get(0),query.get(1),1,new HashSet<>());
}
return result;
}
private double dfs(Map<String,Map<String,Double>> graph , String dividend , String dividor , double val ,Set<String> visited){
if(!graph.containsKey(dividend) || !graph.containsKey(dividor))
return -1.0;
if(dividend.equals(dividor))
return 1.0;
if(graph.get(dividend).containsKey(dividor))
return val * graph.get(dividend).get(dividor);
visited.add(dividend);
for(Map.Entry<String,Double> entry : graph.get(dividend).entrySet()){
String key = entry.getKey();
if(!visited.contains(key)){
double nowVal = dfs(graph,entry.getKey(),dividor,val*entry.getValue(),visited);
if(-1 != nowVal)
return nowVal;
}
}
visited.remove(dividend);
return -1.0;
}
}