From 77f448ec961c4547fb2e2a70356020e760ed7c55 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: Wed, 16 Aug 2023 14:38:49 +0800 Subject: [PATCH 1/4] =?UTF-8?q?0332.=E9=87=8D=E6=96=B0=E5=AE=89=E6=8E=92?= =?UTF-8?q?=E8=A1=8C=E7=A8=8B=EF=BC=8C=E6=B7=BB=E5=8A=A0java=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0332.重新安排行程.md | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/problems/0332.重新安排行程.md b/problems/0332.重新安排行程.md index fcdeae7b..2498fbfe 100644 --- a/problems/0332.重新安排行程.md +++ b/problems/0332.重新安排行程.md @@ -261,6 +261,84 @@ 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; From 00f2aa679318c12921ce974168ad3b7728bc0ac5 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: Wed, 16 Aug 2023 15:28:28 +0800 Subject: [PATCH 2/4] =?UTF-8?q?0051.N=E7=9A=87=E5=90=8E=EF=BC=8Cjava?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0051.N皇后.md | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/problems/0051.N皇后.md b/problems/0051.N皇后.md index 6bc4fa78..71c40238 100644 --- a/problems/0051.N皇后.md +++ b/problems/0051.N皇后.md @@ -345,6 +345,58 @@ class Solution { } } ``` +```java +//该方法主要特点在于用一个一维数组暂存皇后的位置,数组下标代表行,数组下标的值代表列,并初始化一个长度为n-1,值全为'.'的模板字符串 +//在找到合法方案时,遍历数组,在模板字符串下标为数组值的位置插入Q +class Solution { + //结果 + List> result = new ArrayList<>(); + //储存皇后的位置,下标为行,值为列 + int[] queenIndex; + //棋盘中一行的字符串模板 + String template; + int size; + + public List> solveNQueens(int n) { + size = n; + template = ".".repeat(n - 1); + queenIndex = new int[n]; + deal(0); + return result; + } + + void deal(int index) { + //遍历当前行的所有位置(尝试在这行每个位置放置皇后) + for (int i = 0; i < size; i++) { + queenIndex[index] = i; + //检查在当前位置放置皇后是否合法 + if (check(index, i)) { + //如果当前的行是最后一行,就说明当前皇后的摆放已经是完整并且合法的,在结果集中加入当前的摆放方案 + if (index == size - 1) { + List tmp = new ArrayList<>(size); + //遍历当前的皇后位置,在模板字符串对应的位置加入Q,再加入到结果集中 + for (Integer integer : queenIndex) { + tmp.add(new StringBuilder(template).insert(integer, "Q").toString()); + } + result.add(tmp); + return; + } + //如果当前不是最后一行,还需要进入下一行 + deal(index + 1); + } + } + } + + boolean check(int rowIndex, int columnIndex) { + for (int i = 0; i < rowIndex; i++) { + if (queenIndex[i] == columnIndex || (Math.abs(queenIndex[i] - columnIndex) == Math.abs(i - rowIndex))) { + return false; + } + } + return true; + } +} +``` ### Python From 99eb035fee885decbd4438145c3f48d28e981e23 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:12:04 +0800 Subject: [PATCH 3/4] =?UTF-8?q?Update=200051.N=E7=9A=87=E5=90=8E.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0051.N皇后.md | 52 ---------------------------------------- 1 file changed, 52 deletions(-) diff --git a/problems/0051.N皇后.md b/problems/0051.N皇后.md index 71c40238..6bc4fa78 100644 --- a/problems/0051.N皇后.md +++ b/problems/0051.N皇后.md @@ -345,58 +345,6 @@ class Solution { } } ``` -```java -//该方法主要特点在于用一个一维数组暂存皇后的位置,数组下标代表行,数组下标的值代表列,并初始化一个长度为n-1,值全为'.'的模板字符串 -//在找到合法方案时,遍历数组,在模板字符串下标为数组值的位置插入Q -class Solution { - //结果 - List> result = new ArrayList<>(); - //储存皇后的位置,下标为行,值为列 - int[] queenIndex; - //棋盘中一行的字符串模板 - String template; - int size; - - public List> solveNQueens(int n) { - size = n; - template = ".".repeat(n - 1); - queenIndex = new int[n]; - deal(0); - return result; - } - - void deal(int index) { - //遍历当前行的所有位置(尝试在这行每个位置放置皇后) - for (int i = 0; i < size; i++) { - queenIndex[index] = i; - //检查在当前位置放置皇后是否合法 - if (check(index, i)) { - //如果当前的行是最后一行,就说明当前皇后的摆放已经是完整并且合法的,在结果集中加入当前的摆放方案 - if (index == size - 1) { - List tmp = new ArrayList<>(size); - //遍历当前的皇后位置,在模板字符串对应的位置加入Q,再加入到结果集中 - for (Integer integer : queenIndex) { - tmp.add(new StringBuilder(template).insert(integer, "Q").toString()); - } - result.add(tmp); - return; - } - //如果当前不是最后一行,还需要进入下一行 - deal(index + 1); - } - } - } - - boolean check(int rowIndex, int columnIndex) { - for (int i = 0; i < rowIndex; i++) { - if (queenIndex[i] == columnIndex || (Math.abs(queenIndex[i] - columnIndex) == Math.abs(i - rowIndex))) { - return false; - } - } - return true; - } -} -``` ### Python 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 4/4] =?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数组