From 7d770507c3217eb69bd0b15ec4a8eb6bfad56010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=93=88=E5=93=88=E5=93=88?= <76643786+Projecthappy@users.noreply.github.com> Date: Tue, 29 Aug 2023 11:23:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84java=E6=96=B0=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0332.重新安排行程.md | 151 ++++++++++++++-------------- 1 file changed, 73 insertions(+), 78 deletions(-) diff --git a/problems/0332.重新安排行程.md b/problems/0332.重新安排行程.md index 2498fbfe..ab144f43 100644 --- a/problems/0332.重新安排行程.md +++ b/problems/0332.重新安排行程.md @@ -261,84 +261,6 @@ for (pair& target : targets[result[result.size() - 1]]) ### Java -```java -/* 首先遍历所有机票,将机票转换成map,其中起点作为key,终点按照字典顺序插入到终点的列表中 - 然后进入递归,递归中首先在result中加入当前位置,如果票用完了就说明这条路走通了 - 递归中遍历从当前位置出发的终点(也就是map中key为当前位置的列表),因为列表是有序的,因此只要出现能走通的路径,这条路径就是字典排序最低的 - 在遍历中,首先从map中移除当前的机票,将遍历到的终点作为起点进入下一层的递归中,如果发现当前机票往后走走不通,再把当前的机票加到map中*/ -class Solution { - //key为起点,value是有序的终点的列表 - Map> ticketMap = new HashMap<>(); - LinkedList result = new LinkedList<>(); - - public List findItinerary(List> tickets) { - //遍历tickets,存入ticketMap中 - for (List ticket : tickets) { - addNew(ticket.get(0), ticket.get(1)); - } - deal("JFK"); - return result; - } - - boolean deal(String currentLocation) { - result.add(currentLocation); - //机票全部用完,找到最小字符路径 - if (ticketMap.isEmpty()) { - return true; - } - //当前位置的终点列表 - LinkedList targetLocations = ticketMap.get(currentLocation); - //机票没用完,但是没有从当前位置出发的机票了,说明这条路走不通 - if (targetLocations == null) { - return false; - } - //终点列表中遍历到的终点 - String targetLocation; - //遍历从当前位置出发的机票 - for (int i = 0; i < targetLocations.size(); i++) { - targetLocation = targetLocations.get(i); - //删除map中的机票,如果当前位置只有一个终点,直接删除k,v,有多个终点则删除终点列表中当前的终点 - if (targetLocations.size() == 1) { - ticketMap.remove(currentLocation); - } else { - targetLocations.remove(i); - } - //递归 - if (deal(targetLocation)) { - return true; - } else { - //路线走不通,将机票重新加到map中 - addNew(currentLocation, targetLocation); - result.removeLast(); - } - } - return false; - } - - /** - * 在map中添加新元素 - * - * @param start 起点 - * @param end 终点 - */ - void addNew(String start, String end) { - LinkedList startAllEnd = ticketMap.get(start); - if (startAllEnd != null) { - for (int i = 0; i < startAllEnd.size() + 1; i++) { - if (i == startAllEnd.size() || end.compareTo(startAllEnd.get(i)) < 0) { - startAllEnd.add(i, end); - break; - } - } - } else { - LinkedList ends = new LinkedList<>(); - ends.add(end); - ticketMap.put(start, ends); - } - } -} -``` - ```java class Solution { private LinkedList res; @@ -423,6 +345,79 @@ class Solution { } ``` +```java +/* 该方法是对第二个方法的改进,主要变化在于将某点的所有终点变更为链表的形式,优点在于 + 1.添加终点时直接在对应位置添加节点,避免了TreeMap增元素时的频繁调整 + 2.同时每次对终点进行增加删除查找时直接通过下标操作,避免hashMap反复计算hash*/ +class Solution { + //key为起点,value是有序的终点的列表 + Map> ticketMap = new HashMap<>(); + LinkedList result = new LinkedList<>(); + int total; + + public List findItinerary(List> tickets) { + total = tickets.size() + 1; + //遍历tickets,存入ticketMap中 + for (List ticket : tickets) { + addNew(ticket.get(0), ticket.get(1)); + } + deal("JFK"); + return result; + } + + boolean deal(String currentLocation) { + result.add(currentLocation); + //机票全部用完,找到最小字符路径 + if (result.size() == total) { + return true; + } + //当前位置的终点列表 + LinkedList targetLocations = ticketMap.get(currentLocation); + //没有从当前位置出发的机票了,说明这条路走不通 + if (targetLocations != null && !targetLocations.isEmpty()) { + //终点列表中遍历到的终点 + String targetLocation; + //遍历从当前位置出发的机票 + for (int i = 0; i < targetLocations.size(); i++) { + targetLocation = targetLocations.get(i); + //删除终点列表中当前的终点 + targetLocations.remove(i); + //递归 + if (deal(targetLocation)) { + return true; + } + //路线走不通,将机票重新加回去 + targetLocations.add(i, targetLocation); + result.removeLast(); + } + } + return false; + } + + /** + * 在map中按照字典顺序添加新元素 + * + * @param start 起点 + * @param end 终点 + */ + void addNew(String start, String end) { + LinkedList startAllEnd = ticketMap.getOrDefault(start, new LinkedList<>()); + if (!startAllEnd.isEmpty()) { + for (int i = 0; i < startAllEnd.size(); i++) { + if (end.compareTo(startAllEnd.get(i)) < 0) { + startAllEnd.add(i, end); + return; + } + } + startAllEnd.add(startAllEnd.size(), end); + } else { + startAllEnd.add(end); + ticketMap.put(start, startAllEnd); + } + } +} +``` + ### Python 回溯 使用used数组