332. Reconstruct Itinerary
思路
- 要先将思维转换到图,每个点都可以看做是图上的一个点
- 这不是dfs,因为不只是遍历,而是顺序遍历所有路径,即一笔画欧拉路径问题
参考
wikipedia
理解
Hierholzer’s algorithm
建立两个栈,一个是tmp暂时暂存元素栈,一个是final最终的结果栈
开始循环
从图中任一点出发,任意访问相邻得点,该节点放入tmp中
当一个节点周围没有相邻节点时,则将该节点从tmp移入到final中,设置当前结点为tmp的栈顶
当所有边均被访问,此过程结束
最后,将tmp放入final中
final的出栈顺序即为路径
还有本题目有个一个重要的数据结构Map<String, PriorityQueue<String>> flights
PriorityQueue<String>可以排序,而map记录每个点的边集
代码
递归法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| Map<String, PriorityQueue<String>> flights; LinkedList<String> path; public List<String> findItinerary(String[][] tickets) { flights = new HashMap<>(); path = new LinkedList<>(); for (String[] ticket : tickets) { if(!flights.containsKey(ticket[0])){ flights.put(ticket[0], new PriorityQueue<String>()); } flights.get(ticket[0]).add(ticket[1]); } dfs("JFK"); return path; } public void dfs(String departure) { PriorityQueue<String> arrivals = flights.get(departure); //访问所有的相邻节点 while (arrivals != null && !arrivals.isEmpty()) dfs(arrivals.poll()); //注意是加到队头! path.addFirst(departure); }
|
非递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| //这里的flights中只包含有邻居的节点 Map<String, PriorityQueue<String>> flights; //返回值 LinkedList<String> path; public List<String> findItinerary(String[][] tickets) { //使用优先队列来记录相邻接点且保证了字典顺序 flights = new HashMap<String, PriorityQueue<String>>(); path = new LinkedList<String>(); if (tickets == null || tickets.length == 0) { return path; } for(String[] s : tickets){ if(!flights.containsKey(s[0])){ flights.put(s[0], new PriorityQueue<String>()); } flights.get(s[0]).add(s[1]); } //http://www.graph-magics.com/articles/euler.php //设置一个退回栈就是circle,存放没有相邻接点的点 //1.从开始节点遍历,将每个有相邻接点的点加入到结果集stack中 //2.如果当前结点无相邻接点,则将其放入退回栈 //3.然后在结果集中逆序选取有相邻接点的点作为当前结点 //4.继续123,直到遍历过所有的边 //5.最后将结果集并入到退回栈circle中 Stack<String> circle = new Stack<String>(); Stack<String> stack = new Stack<String>(); String cur = "JFK"; for(int i = 0; i < tickets.length; i++){ while(!flights.containsKey(cur) || flights.get(cur).size() == 0){ circle.add(cur); cur = stack.pop(); } stack.add(cur); cur = flights.get(cur).poll(); } //最后一个节点一定是没有邻接点的点,因此要放到退回栈circle中 circle.add(cur); //结果集并入到退回栈中 while(!stack.isEmpty()){ circle.add(stack.pop()); } //退回栈的逆序为最终路径 while(!circle.isEmpty()){ path.add(circle.pop()); } return path; }
|