日渐头秃的代码日记 --1 课程表难题

178 阅读1分钟

原题目链接

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程  bi 。 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。 请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。  

示例 1: 输入:numCourses = 2, prerequisites = [[1,0]] 输出:true 解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。 示例 2: 输入:numCourses = 2, prerequisites = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。

class SolutionCourses:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        self.requistes_dict = defaultdict(list)
        self.flag = True
        for course, pre in prerequisites:
            if course == pre:
                return False
            self.requistes_dict[str(course)].append(pre)  # 可能存在一个课程依赖多个前置课程
        self.courses_list = [x for x in range(numCourses)]
        self.visited = [0] * numCourses
        for i in range(numCourses):
            self.dfs(i)
            if self.flag == False:
                return False
        return True
    
    def dfs(self, x):
        self.visited[x] = 1  # 用1 记录本次查找中
        if str(x) in self.requistes_dict.keys():
            vl = self.requistes_dict[str(x)]
        else:
            vl = [-1]
        if vl == [-1]:
            pass
        else:
            for v in vl: 
                if self.visited[v] == 1:
                    self.flag = False
                    return
                elif self.visited[v] == 0:
                    self.dfs(v) # 找下一个课程
        self.visited[x] = 2 # 用2 记录已经完成一趟查找

# course_solution = SolutionCourses()
# numCourses = 5
# prerequisites = [[1,4],[2,4],[3,1],[3,2]]
# print(course_solution.canFinish(numCourses, prerequisites))

这里特别要注意课程的依赖关系,有可能有的课程谁都不依赖,也有可能同时依赖多门其他课程,只要发现了循环依赖,就可以直接返回False。