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. 可以把输入的等式看做一个加权有向图,除数和被除数看做点,计算的结果看做这条边的权。
2. 题目的要求即可转变为判断一个图中是否存在从一个点到另一个点的路径,若存在,则求出经过的所有边的权值的乘积,可以利用DFS遍历。
3. 利用HashMap<String,HashMap<String,Double>>来储存图,键值String用来保存起点,对应的值HashMap用来保存该点的邻接点以及边的权值。
代码如下:
public class Solution {
private Map<String,HashMap<String,Double>> graph;
private Set<String> record;
public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
graph = new HashMap<>();
record = new HashSet<>();
initGraph(equations,values);
double[] result = new double[queries.length];
int i = 0;
for(String[] query : queries){
record.clear();
result[i++] = calcByDFS(query[0],query[1],1);
}
return result;
}
public void initGraph(String[][] equations, double[] values){
int i = 0;
for(String[] equation:equations){
String num1 = equation[0];
String num2 = equation[1];
double value = values[i++];
saveEdg(num1,num2,value);
saveEdg(num2,num1,1.0/value);
}
}
public void saveEdg(String num1,String num2,double value){
HashMap<String,Double> edges = graph.get(num1);
if(edges == null){
edges = new HashMap<>();
graph.put(num1,edges);
}
edges.put(num2,value);
}
public double calcByDFS(String start,String end,double value){
if(!graph.containsKey(start) || !graph.containsKey(end)) return -1;
if(start.equals(end)) return value;
if(record.contains(start)) return -1;
record.add(start);
Map<String,Double> edges = graph.get(start);
for(String str : edges.keySet()){
double result = calcByDFS(str,end,value*edges.get(str));
if(result != -1){
return result;
}
}
return -1;
}
}
Problem 332 Reconstruct Itinerary
Given a list of airline tickets represented by pairs of departure and arrival airports [from, to]
, reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK
. Thus, the itinerary must begin with JFK
.
Note:
- If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary
["JFK", "LGA"]
has a smaller lexical order than["JFK", "LGB"]
. - All airports are represented by three capital letters (IATA code).
- You may assume all tickets form at least one valid itinerary.
Example 1:
tickets
= [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Return ["JFK", "MUC", "LHR", "SFO", "SJC"]
.
Example 2:
tickets
= [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Return ["JFK","ATL","JFK","SFO","ATL","SFO"]
.
Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"]
. But it is larger in lexical order.
解题思路:
1. 也可以把输入的机票看做一个有向图,各个起点终点都是图上的点
2. 于是题目的要求可以转变为判断图中是否存在从一点出发能遍历所有点的路径
3. 图用 HashMap<String,ArrayList<String>>来保存,键值保存出发站,后面的arraylist用来保存出发站能到的各个到达站
4. 对于题目中的要求的smallest lexical order,只需要保存各个出发站的到达站时,按照smallest lexical order来保存,然后按照顺序遍历时,最先得到的路径一定是满足要求的路径
代码如下:
public class Solution {
public static String DEPARTURE = "JFK";
private HashMap<String,ArrayList<String>> graph;
private List<String> result;
private int sum;
public List<String> findItinerary(String[][] tickets) {
graph = new HashMap<>();
result = new ArrayList<>();
sum = tickets.length + 1;
initGraph(tickets);
result.add(DEPARTURE);
find(1,DEPARTURE);
return result;
}
public void initGraph(String[][] tickets){
for(String[] ticket : tickets){
if(graph.get(ticket[0]) == null){
ArrayList<String> arrival = new ArrayList();
graph.put(ticket[0],arrival);
}
addList(graph.get(ticket[0]),ticket[1]);
}
}
public void addList(ArrayList<String> list, String str){
if(list.size() == 0){
list.add(str);
}
else{
int i =0;
while(i < list.size()){
if(str.compareTo(list.get(i)) <= 0){
list.add(i,str);
return;
}
i++;
}
list.add(str);
}
return;
}
public boolean find(int count,String str){
if(count >= sum) return true;
if(!graph.containsKey(str) || graph.get(str).size() == 0) return false;
count++;
ArrayList<String> list = graph.get(str);
int i = 0;
while(i < list.size()){
String s = list.remove(i);
result.add(s);
if(find(count,s)){
return true;
}
addList(list,s);
result.remove(result.size() - 1);
i++;
}
return false;
}
}