1. 程式人生 > >leetcode刷題筆記-topological sort拓撲排序(DFS)

leetcode刷題筆記-topological sort拓撲排序(DFS)

207. Course Schedule 找環

There are a total of n courses you have to take, labeled from 0 to n-1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

Example 1:

Input: 2, [[1,0]] 
Output: true
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0. So it is possible.

Example 2:

Input: 2, [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take. 
             To take course 1 you should have finished course 0, and to take course 0 you should
             also have finished course 1. So it is impossible.

思路:找是否存在環,已經訪問完的標記為1,正在訪問的標記為2,如果遇到正在訪問的就是遇到環

class Solution(object):
    def canFinish(self, numCourses, prerequisites):
        """
        :type numCourses: int
        :type prerequisites: List[List[int]]
        :rtype: bool
        """
        mark = collections.defaultdict(int)
        prere = collections.defaultdict(list)
        for c, p in prerequisites:
            prere[c].append(p)

        def dfs(course):
            if mark[course] == 1:  # visited
                return True

            if mark[course] == 2:  # visiting
                return False

            # unvisited
            mark[course] = 2  # mark as visiting
            preCourses = prere[course]
            if preCourses == []:
                mark[course] = 1
                return True
            else:
                for preCourse in preCourses:
                    re = dfs(preCourse)
                    if not re:
                        return False
                mark[course] = 1  # mark as visited
                return True

        for course, pre in prerequisites:
            re = dfs(course)
            if not re:
                return False
        return True

210. Course Schedule II 拓撲排序

There are a total of n courses you have to take, labeled from 0 to n-1.

Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]

Given the total number of courses and a list of prerequisite pairs, return the ordering of courses you should take to finish all courses.

There may be multiple correct orders, you just need to return one of them. If it is impossible to finish all courses, return an empty array.

Example 1:

Input: 2, [[1,0]] 
Output: [0,1]
Explanation: There are a total of 2 courses to take. To take course 1 you should have finished   
             course 0. So the correct course order is [0,1] .

Example 2:

Input: 4, [[1,0],[2,0],[3,1],[3,2]]
Output: [0,1,2,3] or [0,2,1,3]
Explanation: There are a total of 4 courses to take. To take course 3 you should have finished both     
             courses 1 and 2. Both courses 1 and 2 should be taken after you finished course 0. 
             So one correct course order is [0,1,2,3]. Another correct ordering is [0,2,1,3] .

class Solution(object):
    def findOrder(self, numCourses, prerequisites):
        """
        :type numCourses: int
        :type prerequisites: List[List[int]]
        :rtype: List[int]
        """
        self.graph = collections.defaultdict(list)
        self.res = []
        for c, p in prerequisites:
            self.graph[c].append(p)
        
        self.visited = [0 for x in xrange(numCourses)]
        for node in xrange(numCourses):
            if not self.DFS(node):
                return []
        
        return self.res
        
    
    def DFS(self, node):
        if self.visited[node] == -1:  # visiting
            return False
        if self.visited[node] == 1:  # visited and add to res
            return True 
        self.visited[node] = -1  # mark as visiting
        
        for x in self.graph[node]:
            if not self.DFS(x):
                return False
            
        self.visited[node] = 1
        self.res.append(node)
        return True
        

269. Alien Dictionary

class Solution(object):
    def alienOrder(self, words):
        # a ->b
        adj = collections.defaultdict(set)
        
        # 入度
        degree = {c: 0 for w in words for c in w}
        
        for i, w1 in enumerate(words[:-1]):
            w2 = words[i+1]
            for c1, c2 in zip(w1, w2):
                if c1 == c2:
                    continue
                
                if c2 not in adj[c1]:
                    adj[c1].add(c2)
                    degree[c2] += 1
                break  # 需要break 因為word1, word2 比較,e.x. za,zb 比較的是 a和b。 而ab , ca 比較的是a和c, 和 b,a無關
        res = ''
        # start w 0 indegree nodes
        q = [c for c in degree if not degree[c]]
        while q:
            c = q.pop(0)
            res += c
            for n in adj[c]:
                degree[n] -= 1
                if degree[n] == 0:
                    q.append(n)
        return res if len(res) == len(degree) else ''