LeetCode 399.Evaluate Division & 332.Reconstruct Itinerary

Problem 399 Evaluate Division

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:

  1. 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"].
  2. All airports are represented by three capital letters (IATA code).
  3. 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;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值