leedcode #210 Course Schedule II
Problem Description
Key points:
- Determine whether a directed graph is cyclic.
- Output topological ordering.
Tips
Build a directed graph
Define a new class + defaultdict
Define a new class
class GNode(object):
def __init__(self):
self.inDegree = 0
self.outNode = []
- Use self.inDegree rather than inDegree.
Defaultdict
import collections from defaultdict
graph = defaultdict(GNode)
- Pay attention to the spelling of defaultdict
- How does collections.defaultdict work?
The defaultdict will create a default item (according to your definition) when you try to get an item with a key that is not currently in the dictionary.intDict = defaultdict(int) # default item = 0 listDict = defaultdict(list) # default item = []
Deque
from collections import deque
nodeOrder = deque()
nodeOrder.append(node1) # append a new node to tail
nodeOrder.appendleft(node2) # append a new node to head
nodeOrder.pop() # pop from tail
nodeOrder.popleft() # pop from head
## Topological ordering
Topological ordering
- Data structure: deque
- Intuition:
2.1 Add all nodes with inDegree == 0 into the deque
2.2 In each iteration, pop a node with inDegree == 0, the indegree of the outNode relating to this node minus 1. If there exists new node with inDegree == 0, add it into the deque. Repeat untill the deque is empty.
2.3 Whether is cyclic: if all edges can be removed -> no cycle, vice versa.
Code
class GNode(object):
def __init__(self):
self.inDegree = 0
self.outNode = []
class Solution(object):
def findOrder(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: List[int]
"""
from collections import defaultdict, deque
graph = defaultdict(GNode)
courseOrder = []
for prerequisite in prerequisites:
nextCourse, prevCourse = prerequisite[0], prerequisite[1]
graph[prevCourse].outNode.append(nextCourse)
graph[nextCourse].inDegree += 1
totalEdges = len(prerequisites)
nodepCourses = deque()
for course in range(numCourses):
if graph[course].inDegree == 0:
nodepCourses.append(course)
removedEdges = 0
while nodepCourses:
course = nodepCourses.popleft()
courseOrder.append(course)
for node in graph[course].outNode:
graph[node].inDegree -= 1
removedEdges += 1
if graph[node].inDegree == 0:
nodepCourses.append(node)
if totalEdges == removedEdges:
return courseOrder
return []