@@ -104,7 +104,241 @@ print (r)
104104
105105## 2) LC Example
106106
107- ### 2-1) Course Schedule
107+ ### 2-2) Course Schedule II
108+
109+ ``` java
110+ // java
111+ // LC 210
112+ public class CourseSchedule2 {
113+
114+ // V0
115+ // IDEA : TOPOLOGICAL SORT (fixed by gpt)
116+ // ref : https://github.com/yennanliu/CS_basics/blob/master/leetcode_java/src/main/java/AlgorithmJava/TopologicalSortV2.java
117+ public int [] findOrder (int numCourses , int [][] prerequisites ) {
118+ if (numCourses == 1 ) {
119+ return new int []{0 };
120+ }
121+
122+ // topologic ordering
123+ List<Integer > ordering = topologicalSort(numCourses, prerequisites);
124+ // System.out.println(">>> ordering = " + ordering);
125+ if (ordering == null ){
126+ return new int []{};
127+ }
128+ int [] res = new int [numCourses];
129+ for (int x = 0 ; x < ordering. size(); x++ ) {
130+ int val = ordering. get(x);
131+ // System.out.println(val);
132+ res[x] = val;
133+ }
134+
135+ return res;
136+ }
137+
138+ public List<Integer > topologicalSort (int numNodes , int [][] edges ) {
139+ // Step 1: Build the graph and calculate in-degrees
140+ Map<Integer , List<Integer > > graph = new HashMap<> ();
141+ int [] inDegree = new int [numNodes];
142+
143+ for (int i = 0 ; i < numNodes; i++ ) {
144+ graph. put(i, new ArrayList<> ());
145+ }
146+
147+ for (int [] edge : edges) {
148+ int from = edge[0 ];
149+ int to = edge[1 ];
150+ graph. get(from). add(to);
151+ inDegree[to]++ ;
152+ }
153+
154+ // Step 2: Initialize a queue with nodes that have in-degree 0
155+ Queue<Integer > queue = new LinkedList<> ();
156+ for (int i = 0 ; i < numNodes; i++ ) {
157+ /**
158+ * NOTE !!!
159+ *
160+ * we add ALL nodes with degree = 0 to queue at init step
161+ */
162+ if (inDegree[i] == 0 ) {
163+ queue. offer(i);
164+ }
165+ }
166+
167+ List<Integer > topologicalOrder = new ArrayList<> ();
168+
169+ // Step 3: Process the nodes in topological order
170+ while (! queue. isEmpty()) {
171+ /**
172+ * NOTE !!!
173+ *
174+ * ONLY "degree = 0" nodes CAN be added to queue
175+ *
176+ * -> so we can add whatever node from queue to final result (topologicalOrder)
177+ */
178+ int current = queue. poll();
179+ topologicalOrder. add(current);
180+
181+ for (int neighbor : graph. get(current)) {
182+ inDegree[neighbor] -= 1 ;
183+ /**
184+ * NOTE !!!
185+ *
186+ * if a node "degree = 0" means this node can be ACCESSED now,
187+ *
188+ * -> so we need to add it to the queue (for adding to topologicalOrder in the following while loop iteration)
189+ */
190+ if (inDegree[neighbor] == 0 ) {
191+ queue. offer(neighbor);
192+ }
193+ }
194+ }
195+
196+ // If topologicalOrder does not contain all nodes, there was a cycle in the graph
197+ if (topologicalOrder. size() != numNodes) {
198+ // throw new IllegalArgumentException("The graph has a cycle, so topological sort is not possible.");
199+ return null ;
200+ }
201+
202+ /* * NOTE !!! reverse ordering */
203+ Collections . reverse(topologicalOrder);
204+ return topologicalOrder;
205+ }
206+
207+ ```
208+
209+ ```python
210+ # LC 210 Course Schedule II
211+ # V0
212+ # IDEA : DFS + topological sort
213+ # SAME dfs logic as LC 207 (Course Schedule )
214+ from collections import defaultdict
215+ class Solution (object):
216+ def findOrder(self, numCourses, prerequisites):
217+ # edge case
218+ if not prerequisites:
219+ return [x for x in range(numCourses)]
220+
221+ # help func : dfs
222+ # 3 cases : 0 : unknown, 1 :visiting, 2 : visited
223+ def dfs(idx, visited, g, res):
224+ if visited[idx] == 1:
225+ return False
226+ # NOTE !!! if visited[idx] == 2, means already visited, return True directly (and check next idx in range(numCourses))
227+ if visited[idx] == 2:
228+ return True
229+ visited[idx] = 1
230+ """
231+ NOTE this !!!
232+
233+ 1) for j in g[idx] (but not for i in range(numCourses))
234+ 2) go through idx in g[idx]
235+ """
236+ for j in g[idx]:
237+ if not dfs(j, visited, g, res):
238+ return False
239+ """
240+ don't forget to make idx as visited (visited[idx] = 2)
241+ """
242+ visited[idx] = 2
243+ """
244+ NOTE : the main difference between LC 207, 210
245+
246+ -> we append idx to res (our ans)
247+ """
248+ res.append(idx)
249+ return True
250+ # init
251+ visited = [0] * numCourses
252+ # build grath
253+ g = defaultdict(list)
254+ for p in prerequisites:
255+ g[p[0]].append(p[1])
256+ res = []
257+ """
258+ NOTE : go through idx in numCourses (for idx in range(numCourses))
259+ """
260+ for idx in range(numCourses):
261+ if not dfs(idx, visited, g, res):
262+ return []
263+ return res
264+
265+ # V0'
266+ # IDEA : DFS + topological sort
267+ # SAME dfs logic as LC 207 (Course Schedule)
268+ import collections
269+ class Solution :
270+ def findOrder(self, numCourses, prerequisites):
271+ # build graph
272+ _graph = collections.defaultdict(list)
273+ for i in range(len(prerequisites)):
274+ _graph[prerequisites[i][0]].append(prerequisites[i][1])
275+
276+ visited = [0] * numCourses
277+ res = []
278+ for i in range(numCourses):
279+ if not self.dfs(_graph, visited, i, res):
280+ return []
281+ print ("res = " + str(res))
282+ return res
283+
284+ # 0 : unknown, 1 :visiting, 2 : visited
285+ def dfs(self, _graph, visited, i, res):
286+ if visited[i] == 1:
287+ return False
288+ if visited[i] == 2:
289+ return True
290+ visited[i] = 1
291+ for item in _graph[i]:
292+ if not self.dfs(_graph, visited, item, res):
293+ return False
294+ visited[i] = 2
295+ res.append(i)
296+ return True
297+
298+ # V0'
299+ # IDEA : DFS + topological sort
300+ # SAME dfs logic as LC 207 (Course Schedule)
301+ class Solution (object):
302+ def findOrder(self, numCourses, prerequisites):
303+ """
304+ :type numCourses: int
305+ :type prerequisites: List[List[int]]
306+ :rtype: List[int]
307+ """
308+ graph = collections.defaultdict(list)
309+ for u, v in prerequisites:
310+ graph[u].append(v)
311+ # 0 = Unknown, 1 = visiting, 2 = visited
312+ visited = [0] * numCourses
313+ path = []
314+ for i in range(numCourses):
315+ ### NOTE : if not a valid "prerequisites", then will return NULL list
316+ if not self.dfs(graph, visited, i, path):
317+ return []
318+ return path
319+
320+ def dfs(self, graph, visited, i, path):
321+ # 0 = Unknown, 1 = visiting, 2 = visited
322+ if visited[i] == 1: return False
323+ if visited[i] == 2: return True
324+ visited[i] = 1
325+ for j in graph[i]:
326+ if not self.dfs(graph, visited, j, path):
327+ ### NOTE : the quit condition
328+ return False
329+ visited[i] = 2
330+ path.append(i)
331+ return True
332+ ```
333+
334+ ### 2-2) Course Schedule
335+
336+ ```java
337+ // java
338+ // LC 207
339+ // same as LC 210
340+ ```
341+
108342```python
109343# LC 207 Course Schedule
110344# NOTE : there are also bracktrack, dfs approachs for this problem
@@ -327,132 +561,6 @@ class Solution:
327561 return len(stack) == numCourses
328562```
329563
330- ### 2-2) Course Schedule II
331- ``` python
332- # LC 210 Course Schedule II
333- # V0
334- # IDEA : DFS + topological sort
335- # SAME dfs logic as LC 207 (Course Schedule)
336- from collections import defaultdict
337- class Solution (object ):
338- def findOrder (self , numCourses , prerequisites ):
339- # edge case
340- if not prerequisites:
341- return [x for x in range (numCourses)]
342-
343- # help func : dfs
344- # 3 cases : 0 : unknown, 1 :visiting, 2 : visited
345- def dfs (idx , visited , g , res ):
346- if visited[idx] == 1 :
347- return False
348- # NOTE !!! if visited[idx] == 2, means already visited, return True directly (and check next idx in range(numCourses))
349- if visited[idx] == 2 :
350- return True
351- visited[idx] = 1
352- """
353- NOTE this !!!
354-
355- 1) for j in g[idx] (but not for i in range(numCourses))
356- 2) go through idx in g[idx]
357- """
358- for j in g[idx]:
359- if not dfs(j, visited, g, res):
360- return False
361- """
362- don't forget to make idx as visited (visited[idx] = 2)
363- """
364- visited[idx] = 2
365- """
366- NOTE : the main difference between LC 207, 210
367-
368- -> we append idx to res (our ans)
369- """
370- res.append(idx)
371- return True
372- # init
373- visited = [0 ] * numCourses
374- # build grath
375- g = defaultdict(list )
376- for p in prerequisites:
377- g[p[0 ]].append(p[1 ])
378- res = []
379- """
380- NOTE : go through idx in numCourses (for idx in range(numCourses))
381- """
382- for idx in range (numCourses):
383- if not dfs(idx, visited, g, res):
384- return []
385- return res
386-
387- # V0'
388- # IDEA : DFS + topological sort
389- # SAME dfs logic as LC 207 (Course Schedule)
390- import collections
391- class Solution :
392- def findOrder (self , numCourses , prerequisites ):
393- # build graph
394- _graph = collections.defaultdict(list )
395- for i in range (len (prerequisites)):
396- _graph[prerequisites[i][0 ]].append(prerequisites[i][1 ])
397-
398- visited = [0 ] * numCourses
399- res = []
400- for i in range (numCourses):
401- if not self .dfs(_graph, visited, i, res):
402- return []
403- print (" res = " + str (res))
404- return res
405-
406- # 0 : unknown, 1 :visiting, 2 : visited
407- def dfs (self , _graph , visited , i , res ):
408- if visited[i] == 1 :
409- return False
410- if visited[i] == 2 :
411- return True
412- visited[i] = 1
413- for item in _graph[i]:
414- if not self .dfs(_graph, visited, item, res):
415- return False
416- visited[i] = 2
417- res.append(i)
418- return True
419-
420- # V0'
421- # IDEA : DFS + topological sort
422- # SAME dfs logic as LC 207 (Course Schedule)
423- class Solution (object ):
424- def findOrder (self , numCourses , prerequisites ):
425- """
426- :type numCourses: int
427- :type prerequisites: List[List[int]]
428- :rtype: List[int]
429- """
430- graph = collections.defaultdict(list )
431- for u, v in prerequisites:
432- graph[u].append(v)
433- # 0 = Unknown, 1 = visiting, 2 = visited
434- visited = [0 ] * numCourses
435- path = []
436- for i in range (numCourses):
437- # ## NOTE : if not a valid "prerequisites", then will return NULL list
438- if not self .dfs(graph, visited, i, path):
439- return []
440- return path
441-
442- def dfs (self , graph , visited , i , path ):
443- # 0 = Unknown, 1 = visiting, 2 = visited
444- if visited[i] == 1 : return False
445- if visited[i] == 2 : return True
446- visited[i] = 1
447- for j in graph[i]:
448- if not self .dfs(graph, visited, j, path):
449- # ## NOTE : the quit condition
450- return False
451- visited[i] = 2
452- path.append(i)
453- return True
454- ```
455-
456564### 2-3) alien-dictionary
457565```python
458566# 269 alien-dictionary
0 commit comments