From bfb838be538aa052f73aa12b2bf2a94974460f49 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Mon, 10 Jun 2024 16:43:54 +0800 Subject: [PATCH] update 207 java, py, cheatsheet, progress --- data/progress.txt | 4 +- data/to_review.txt | 32 +++--- doc/cheatsheet/backtrack.md | 101 +++++++++++++++++ doc/cheatsheet/bfs.md | 2 +- .../java/LeetCodeJava/BFS/CourseSchedule.java | 92 ++++++++++++++- .../src/main/java/dev/workspace3.java | 105 ++++++++++++++++++ .../Breadth-First-Search/course-schedule.py | 34 ++++++ 7 files changed, 349 insertions(+), 21 deletions(-) diff --git a/data/progress.txt b/data/progress.txt index 18ea5e9fa..65bd6cf83 100644 --- a/data/progress.txt +++ b/data/progress.txt @@ -1,5 +1,5 @@ -20240610: 22(ok*) -20240609: 236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo) +20240610: 22(ok*),207(todo),210(todo) +20240609: 236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo) 20240608: 503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77 20240607: 235(ok),236(again),496(ok),110(ok),1448(again!) 20240606: 206,143,138(again),141,needcode_tree,226,104,110(again!!!) diff --git a/data/to_review.txt b/data/to_review.txt index a959d9cb0..f0931ecab 100644 --- a/data/to_review.txt +++ b/data/to_review.txt @@ -1,5 +1,5 @@ -2024-08-04 -> ['22(ok*)'] -2024-08-03 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)'] +2024-08-04 -> ['22(ok*),207(todo),210(todo)'] +2024-08-03 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)'] 2024-08-02 -> ['503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77'] 2024-08-01 -> ['235(ok),236(again),496(ok),110(ok),1448(again!)'] 2024-07-31 -> ['206,143,138(again),141,needcode_tree,226,104,110(again!!!)'] @@ -18,8 +18,8 @@ 2024-07-17 -> ['56'] 2024-07-16 -> ['62,572,57'] 2024-07-15 -> ['322,191,190'] -2024-07-14 -> ['22(ok*)', '73,200,70,323(again)'] -2024-07-13 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '207,79,206,213,198'] +2024-07-14 -> ['22(ok*),207(todo),210(todo)', '73,200,70,323(again)'] +2024-07-13 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '207,79,206,213,198'] 2024-07-12 -> ['503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '212(todo),211,338,208(again)'] 2024-07-11 -> ['235(ok),236(again),496(ok),110(ok),1448(again!)', '347,253(todo),91(todo),217'] 2024-07-10 -> ['206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '226,98,253(todo)'] @@ -30,28 +30,28 @@ 2024-07-05 -> ['128,261', '121,252'] 2024-07-04 -> ['005,003(again)', '125'] 2024-07-02 -> ['11,647,261(again),133(again)'] -2024-07-01 -> ['22(ok*)', '143,15,268,141,139'] -2024-06-30 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '21,20,19,271,269'] +2024-07-01 -> ['22(ok*),207(todo),210(todo)', '143,15,268,141,139'] +2024-06-30 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '21,20,19,271,269'] 2024-06-29 -> ['503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '417(again),33,153,152'] 2024-06-28 -> ['235(ok),236(again),496(ok),110(ok),1448(again!)', '424,297(todo),295(todo),39'] 2024-06-27 -> ['206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '55,54(todo),53(again),435(again),49,48(todo),300(again)'] 2024-06-26 -> ['150,22(again),739(again!!!),needcode_linkedlist', '56'] 2024-06-25 -> ['567(todo),needcode_array_hash,needcode_sliding_window,567(again),needcode_stack,155(again)', '62,572,57'] 2024-06-24 -> ['146,460,582(ok*),139(ok),322(todo)', '322,191,190'] -2024-06-23 -> ['22(ok*)', '127,742(again),133(again),207(ok*),261(ok)', '73,200,70,323(again)'] -2024-06-22 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '128,261', '207,79,206,213,198'] +2024-06-23 -> ['22(ok*),207(todo),210(todo)', '127,742(again),133(again),207(ok*),261(ok)', '73,200,70,323(again)'] +2024-06-22 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '128,261', '207,79,206,213,198'] 2024-06-21 -> ['503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '005,003(again)', '212(todo),211,338,208(again)'] 2024-06-20 -> ['235(ok),236(again),496(ok),110(ok),1448(again!)', '347,253(todo),91(todo),217'] 2024-06-19 -> ['206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '11,647,261(again),133(again)', '226,98,253(todo)'] -2024-06-18 -> ['22(ok*)', '150,22(again),739(again!!!),needcode_linkedlist', '143,15,268,141,139', '104,230,102,100'] -2024-06-17 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '567(todo),needcode_array_hash,needcode_sliding_window,567(again),needcode_stack,155(again)', '21,20,19,271,269', '105,106'] +2024-06-18 -> ['22(ok*),207(todo),210(todo)', '150,22(again),739(again!!!),needcode_linkedlist', '143,15,268,141,139', '104,230,102,100'] +2024-06-17 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '567(todo),needcode_array_hash,needcode_sliding_window,567(again),needcode_stack,155(again)', '21,20,19,271,269', '105,106'] 2024-06-16 -> ['503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '146,460,582(ok*),139(ok),322(todo)', '417(again),33,153,152', '242,235'] -2024-06-15 -> ['22(ok*)', '235(ok),236(again),496(ok),110(ok),1448(again!)', '127,742(again),133(again),207(ok*),261(ok)', '424,297(todo),295(todo),39', '371'] -2024-06-14 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '128,261', '55,54(todo),53(again),435(again),49,48(todo),300(again)', '121,252'] -2024-06-13 -> ['22(ok*)', '503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '150,22(again),739(again!!!),needcode_linkedlist', '005,003(again)', '56', '125'] -2024-06-12 -> ['22(ok*)', '236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '235(ok),236(again),496(ok),110(ok),1448(again!)', '567(todo),needcode_array_hash,needcode_sliding_window,567(again),needcode_stack,155(again)', '62,572,57'] -2024-06-11 -> ['22(ok*)', '236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '146,460,582(ok*),139(ok),322(todo)', '11,647,261(again),133(again)', '322,191,190'] -2024-06-10 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),207(todo),261(todo)', '503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '235(ok),236(again),496(ok),110(ok),1448(again!)', '150,22(again),739(again!!!),needcode_linkedlist', '127,742(again),133(again),207(ok*),261(ok)', '143,15,268,141,139', '73,200,70,323(again)'] +2024-06-15 -> ['22(ok*),207(todo),210(todo)', '235(ok),236(again),496(ok),110(ok),1448(again!)', '127,742(again),133(again),207(ok*),261(ok)', '424,297(todo),295(todo),39', '371'] +2024-06-14 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '128,261', '55,54(todo),53(again),435(again),49,48(todo),300(again)', '121,252'] +2024-06-13 -> ['22(ok*),207(todo),210(todo)', '503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '150,22(again),739(again!!!),needcode_linkedlist', '005,003(again)', '56', '125'] +2024-06-12 -> ['22(ok*),207(todo),210(todo)', '236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '235(ok),236(again),496(ok),110(ok),1448(again!)', '567(todo),needcode_array_hash,needcode_sliding_window,567(again),needcode_stack,155(again)', '62,572,57'] +2024-06-11 -> ['22(ok*),207(todo),210(todo)', '236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '146,460,582(ok*),139(ok),322(todo)', '11,647,261(again),133(again)', '322,191,190'] +2024-06-10 -> ['236(again*),1448(again),needcode_trie,208(ok*),needcode_graph,695,22(todo),981(todo),261(todo)', '503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '235(ok),236(again),496(ok),110(ok),1448(again!)', '150,22(again),739(again!!!),needcode_linkedlist', '127,742(again),133(again),207(ok*),261(ok)', '143,15,268,141,139', '73,200,70,323(again)'] 2024-06-09 -> ['503(todo),739(ok),105(todo),needcode_heap_pq,1046,215,needcode_backtrack,78,39(todo),46,90(todo),77', '235(ok),236(again),496(ok),110(ok),1448(again!)', '206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '567(todo),needcode_array_hash,needcode_sliding_window,567(again),needcode_stack,155(again)', '128,261', '21,20,19,271,269', '207,79,206,213,198'] 2024-06-08 -> ['235(ok),236(again),496(ok),110(ok),1448(again!)', '206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '150,22(again),739(again!!!),needcode_linkedlist', '146,460,582(ok*),139(ok),322(todo)', '005,003(again)', '417(again),33,153,152', '212(todo),211,338,208(again)'] 2024-06-07 -> ['206,143,138(again),141,needcode_tree,226,104,110(again!!!)', '150,22(again),739(again!!!),needcode_linkedlist', '567(todo),needcode_array_hash,needcode_sliding_window,567(again),needcode_stack,155(again)', '127,742(again),133(again),207(ok*),261(ok)', '424,297(todo),295(todo),39', '347,253(todo),91(todo),217'] diff --git a/doc/cheatsheet/backtrack.md b/doc/cheatsheet/backtrack.md index 63aeb4de9..b5f02cc5d 100644 --- a/doc/cheatsheet/backtrack.md +++ b/doc/cheatsheet/backtrack.md @@ -1432,4 +1432,105 @@ class Solution: for parent in parents[r[0]]: stack.append([parent]+r) return res +``` + +### 2-11) Course Schedule +```java +// java +// LC 207 +// V0 +// IDEA : DFS (fix by gpt) +// NOTE !!! instead of maintain status (0,1,2), below video offers a simpler approach +// -> e.g. use a set, recording the current visiting course, if ANY duplicated (already in set) course being met, +// -> means "cyclic", so return false directly +// https://www.youtube.com/watch?v=EgI5nU9etnU +public boolean canFinish(int numCourses, int[][] prerequisites) { + // Initialize adjacency list for storing prerequisites + /** + * NOTE !!! + * + * init prerequisites map + * {course : [prerequisites_array]} + * below init map with null array as first step + */ + Map> preMap = new HashMap<>(); + for (int i = 0; i < numCourses; i++) { + preMap.put(i, new ArrayList<>()); + } + + // Populate the adjacency list with prerequisites + /** + * NOTE !!! + * + * update prerequisites map + * {course : [prerequisites_array]} + * so we go through prerequisites, + * then append each course's prerequisites to preMap + */ + for (int[] pair : prerequisites) { + int crs = pair[0]; + int pre = pair[1]; + preMap.get(crs).add(pre); + } + + /** NOTE !!! + * + * init below set for checking if there is "cyclic" case + */ + // Set for tracking courses during the current DFS path + Set visiting = new HashSet<>(); + + // Recursive DFS function + for (int c = 0; c < numCourses; c++) { + if (!dfs(c, preMap, visiting)) { + return false; + } + } + return true; +} + +private boolean dfs(int crs, Map> preMap, Set visiting) { + /** NOTE !!! + * + * if visiting contains current course, + * means there is a "cyclic", + * (e.g. : needs to take course a, then can take course b, and needs to take course b, then can take course a) + * so return false directly + */ + if (visiting.contains(crs)) { + return false; + } + /** + * NOTE !!! + * + * if such course has NO preRequisite, + * return true directly + */ + if (preMap.get(crs).isEmpty()) { + return true; + } + + /** + * NOTE !!! + * + * add current course to set (Set visiting) + */ + visiting.add(crs); + for (int pre : preMap.get(crs)) { + if (!dfs(pre, preMap, visiting)) { + return false; + } + } + /** + * NOTE !!! + * + * remove current course from set, + * since already finish visiting + * + * e.g. undo changes + */ + visiting.remove(crs); + preMap.get(crs).clear(); // Clear prerequisites as the course is confirmed to be processed + return true; +} ``` \ No newline at end of file diff --git a/doc/cheatsheet/bfs.md b/doc/cheatsheet/bfs.md index 627867da1..8a3bf53a9 100644 --- a/doc/cheatsheet/bfs.md +++ b/doc/cheatsheet/bfs.md @@ -365,7 +365,7 @@ class Solution(object): # 207 Couese Schedule # 210 Course Schedule II -# note : there is also a dfs solution +# note : there is also a dfs / backtrack solution # IDEA : BFS class Solution(object): def canFinish(self, N, prerequisites): diff --git a/leetcode_java/src/main/java/LeetCodeJava/BFS/CourseSchedule.java b/leetcode_java/src/main/java/LeetCodeJava/BFS/CourseSchedule.java index 27faecd54..91bf1b0a1 100644 --- a/leetcode_java/src/main/java/LeetCodeJava/BFS/CourseSchedule.java +++ b/leetcode_java/src/main/java/LeetCodeJava/BFS/CourseSchedule.java @@ -7,12 +7,100 @@ public class CourseSchedule { // V0 - // IDEA : DFS - // TODO : implement + // IDEA : DFS (fix by gpt) // NOTE !!! instead of maintain status (0,1,2), below video offers a simpler approach // -> e.g. use a set, recording the current visiting course, if ANY duplicated (already in set) course being met, // -> means "cyclic", so return false directly // https://www.youtube.com/watch?v=EgI5nU9etnU + public boolean canFinish(int numCourses, int[][] prerequisites) { + // Initialize adjacency list for storing prerequisites + /** + * NOTE !!! + * + * init prerequisites map + * {course : [prerequisites_array]} + * below init map with null array as first step + */ + Map> preMap = new HashMap<>(); + for (int i = 0; i < numCourses; i++) { + preMap.put(i, new ArrayList<>()); + } + + // Populate the adjacency list with prerequisites + /** + * NOTE !!! + * + * update prerequisites map + * {course : [prerequisites_array]} + * so we go through prerequisites, + * then append each course's prerequisites to preMap + */ + for (int[] pair : prerequisites) { + int crs = pair[0]; + int pre = pair[1]; + preMap.get(crs).add(pre); + } + + /** NOTE !!! + * + * init below set for checking if there is "cyclic" case + */ + // Set for tracking courses during the current DFS path + Set visiting = new HashSet<>(); + + // Recursive DFS function + for (int c = 0; c < numCourses; c++) { + if (!dfs(c, preMap, visiting)) { + return false; + } + } + return true; + } + + private boolean dfs(int crs, Map> preMap, Set visiting) { + /** NOTE !!! + * + * if visiting contains current course, + * means there is a "cyclic", + * (e.g. : needs to take course a, then can take course b, and needs to take course b, then can take course a) + * so return false directly + */ + if (visiting.contains(crs)) { + return false; + } + /** + * NOTE !!! + * + * if such course has NO preRequisite, + * return true directly + */ + if (preMap.get(crs).isEmpty()) { + return true; + } + + /** + * NOTE !!! + * + * add current course to set (Set visiting) + */ + visiting.add(crs); + for (int pre : preMap.get(crs)) { + if (!dfs(pre, preMap, visiting)) { + return false; + } + } + /** + * NOTE !!! + * + * remove current course from set, + * since already finish visiting + * + * e.g. undo changes + */ + visiting.remove(crs); + preMap.get(crs).clear(); // Clear prerequisites as the course is confirmed to be processed + return true; + } // VO' // IDEA : TOPOLOGICAL SORT diff --git a/leetcode_java/src/main/java/dev/workspace3.java b/leetcode_java/src/main/java/dev/workspace3.java index 7dbc1dfd2..c74c4f392 100644 --- a/leetcode_java/src/main/java/dev/workspace3.java +++ b/leetcode_java/src/main/java/dev/workspace3.java @@ -4890,6 +4890,111 @@ public boolean isValidP(String input){ return true; } + // LC 207 + public boolean canFinish_5(int numCourses, int[][] prerequisites) { + + if (prerequisites.length == 0){ + return true; + } + + if (prerequisites.length == 1 && numCourses == 1){ + return true; + } + + // init + // map : {course, [course_prerequisites]} + Map> map = new HashMap<>(); + for (int[] item : prerequisites){ + if (!map.containsKey(item[0])){ + map.put(item[0], new ArrayList<>()); + }else{ + List cur = map.get(item[0]); + cur.add(item[1]); + map.put(item[0], cur); + } + } + // set : current visiting courses + HashSet set = new HashSet<>(); + HashSet visited = new HashSet<>(); + + // dfs + int cur = 0; // ? + if (!checkPrereq(cur, map, set, visited)){ + return false; + } + return set.size() == numCourses; + } + + public boolean checkPrereq(int cur, Map> map, HashSet set, HashSet visited){ + + visited.add(cur); + + if (set.contains(cur)){ + return false; + } + + set.add(cur); + if (!map.containsKey(cur) || map.get(cur).size() == 0){ + return true; + } + + for (Integer x : map.get(cur)){ + this.checkPrereq(x, map, set, visited); + } + + // undo + set.remove(cur); + + return true; + } + + // LC 207 + //import java.util.*; + public boolean canFinish_6(int numCourses, int[][] prerequisites) { + // Initialize adjacency list for storing prerequisites + Map> preMap = new HashMap<>(); + for (int i = 0; i < numCourses; i++) { + preMap.put(i, new ArrayList<>()); + } + + // Populate the adjacency list with prerequisites + for (int[] pair : prerequisites) { + int crs = pair[0]; + int pre = pair[1]; + preMap.get(crs).add(pre); + } + + // Set for tracking courses during the current DFS path + Set visiting = new HashSet<>(); + + // Recursive DFS function + for (int c = 0; c < numCourses; c++) { + if (!dfs(c, preMap, visiting)) { + return false; + } + } + return true; + } + + private boolean dfs(int crs, Map> preMap, Set visiting) { + if (visiting.contains(crs)) { + return false; + } + if (preMap.get(crs).isEmpty()) { + return true; + } + + visiting.add(crs); + for (int pre : preMap.get(crs)) { + if (!dfs(pre, preMap, visiting)) { + return false; + } + } + visiting.remove(crs); + preMap.get(crs).clear(); // Clear prerequisites as the course is confirmed to be processed + return true; + } + } diff --git a/leetcode_python/Breadth-First-Search/course-schedule.py b/leetcode_python/Breadth-First-Search/course-schedule.py index c9603399e..9c97e08cf 100644 --- a/leetcode_python/Breadth-First-Search/course-schedule.py +++ b/leetcode_python/Breadth-First-Search/course-schedule.py @@ -76,6 +76,40 @@ def dfs(res, graph, visited, x): return False return len(res) > 0 +# V0' +# IDEA : DFS +# https://github.com/neetcode-gh/leetcode/blob/main/python/0207-course-schedule.py +# https://www.youtube.com/watch?v=EgI5nU9etnU +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + # dfs + preMap = {i: [] for i in range(numCourses)} + + # map each course to : prereq list + for crs, pre in prerequisites: + preMap[crs].append(pre) + + visiting = set() + + def dfs(crs): + if crs in visiting: + return False + if preMap[crs] == []: + return True + + visiting.add(crs) + for pre in preMap[crs]: + if not dfs(pre): + return False + visiting.remove(crs) + preMap[crs] = [] + return True + + for c in range(numCourses): + if not dfs(c): + return False + return True + # V0 # IDEA : DFS, LC Course Schedule II from collections import defaultdict