题目:
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.0,若两个字符串相等,则返回1.0。从本质来看是要遍历图,查找是否存在顶点A到另一个顶点的路径,这里我们用邻接表法表示图,然后用一个对应的hashmap保存一个点和其邻接点的比率。然后查找两个字符串之间的比率就变成了求图中一个顶点到一个顶点的路径,然后路径上的值乘积。这里需要注意的是若a/b = c,那么b/a = 1/c;在遍历的时候用一个hashset记录当前被遍历过的点,当当前点已经被遍历过那么这条路径不通,返回0.0。
代码:
public class Solution { public double[] calcEquation(String[][] equations, double[] values, String[][] queries) { int length = equations.length; HashMap<String,ArrayList<String>> neighbors = new HashMap<>(); //记录每个点的邻接顶点 HashMap<String,ArrayList<Double>> neighborsValue = new HashMap<>();//记录个点邻接顶点对应的值 for(int i=0;i<length;i++){ //若a/b = c,那么b/a = 1/c; if(!neighbors.containsKey(equations[i][0])){ neighbors.put(equations[i][0],new ArrayList<>()); neighborsValue.put(equations[i][0],new ArrayList<>()); } if(!neighbors.containsKey(equations[i][1])){ neighbors.put(equations[i][1],new ArrayList<>()); neighborsValue.put(equations[i][1],new ArrayList<>()); } neighbors.get(equations[i][0]).add(equations[i][1]); neighborsValue.get(equations[i][0]).add(values[i]); neighbors.get(equations[i][1]).add(equations[i][0]); neighborsValue.get(equations[i][1]).add(1/values[i]); } double[] res = new double[queries.length]; for(int i=0;i<queries.length;i++){ String a = queries[i][0]; String b = queries[i][1]; res[i] = dfs(1.0,a,b,neighbors,neighborsValue,new HashSet<>());//hashset用来保存已经遍历过的点 if (res[i] == 0.0) res[i] = -1.0; } return res; } public double dfs(double value,String a,String b,HashMap<String,ArrayList<String>> neighbors,HashMap<String,ArrayList<Double>> neighborsValue,HashSet<String> hashSet){ if(hashSet.contains(a)) //已经遍历过该点 return 0.0; if(!neighbors.containsKey(a)) return 0.0; //不存在该点 if(a.equals(b)) return value; hashSet.add(a); //标记为已遍历 List<String> neigh = neighbors.get(a); List<Double> neighValues = neighborsValue.get(a); double tmp = 0.0; for(int i=0;i<neigh.size();i++){ String dot = neigh.get(i); double dotValue = neighValues.get(i); tmp = dfs(value*dotValue,dot,b,neighbors,neighborsValue,hashSet); if(tmp!=0.0) //不为0,那么找到了结果,直接break,不需要继续查找 break; } hashSet.remove(a); return tmp; } }