[Notes] Topological Sort(拓扑排序)

Posted by 西维蜀黍的OJ Blog on 2023-09-13, Last Modified on 2024-02-01

解析

207. Course Schedule

  • 用一个set 记录已经当前路径已经访问过的节点
    • 如果有一个节点被访问了多次,说明有环
  • 递归的访问一个节点的所有 prerequisite,当结束后,把该节点需要的prerequisite 置为 [],然后把该节点从visit 中移除
	# solution 1 - DFS + hashmap - myself
	# time: O(course + prerequisites) # because every course will be accessed up to two times and every dependency edge will be accessed once
	def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
		# {1: [0]} means that course 1 depends on course 0 (i.e. do course 0 first, and then course 1)
		prerequisitesMap = {}
		for course, prerequisite in prerequisites:
			if course not in prerequisitesMap:
				prerequisitesMap[course] = []
			prerequisitesMap[course].append(prerequisite)
	
		# to store all visited courses along the cur DFS path to detect a circle
		pathNodes = set()
		def dfs(course):
			if course in pathNodes:  # means this course has been visited (i.e., we detect a loop), and thus cannot finish all courses
				return False
			if not prerequisitesMap.get(course, []):  # means this course doesn't have prerequisites
				return True
	
			pathNodes.add(course)
			for prerequisite in prerequisitesMap[course]:
				if not dfs(prerequisite):
					return False
			pathNodes.remove(course)  # we need this, an edge case: [[3,1],[1,4],[3,2],[2,4]] got a wrong result
			prerequisitesMap[
				course] = []  # call this function to reduce unnecessary recursion, e.g., [[0,1],[1,3],[3,4],[4,5],[0.4]]
			return True
	
		for course in range(numCourses):
			if not dfs(course):
				return False
		return True

 # BFS TODO	

ref

210. Course Schedule II

	# solution 1 - DFS + hashmap - myself
	# time: O(course + prerequisites) # because every course will be accessed up to two times and every dependency edge will be accessed once
	def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
		prerequisitesMap = {}
		for course, prerequisite in prerequisites:
			if course not in prerequisitesMap:
				prerequisitesMap[course] = []
			prerequisitesMap[course].append(prerequisite)

		# to store all visited courses along the cur DFS path to detect a circle
		pathNodes = set()
		# to avoid an element to be added to res multiple times
		resSet = set()
		res = []

		def dfs(course):
			if course in pathNodes:  # means this course has been visited (i.e., we detect a loop), and thus cannot finish all courses
				return False
			if course in resSet:
				return True

			pathNodes.add(course)
			for prerequisite in prerequisitesMap.get(course, []):
				if not dfs(prerequisite):
					return False

			res.append(course)  # we need this, an edge case: [[3,1],[1,4],[3,2],[2,4]] got a wrong result
			resSet.add(course)
			pathNodes.remove(course)
			return True

		for course in range(numCourses):
			if not dfs(course):
				return []

		return res

ref

ref

Ref