LeetCode 1462. 강좌일정 IV: 토폴로지 정렬

【LetMeFly】1462. 커리큘럼 IV: 위상 정렬

Leetcode 질문 링크: https://leetcode.cn/problems/course-schedule-iv/

총 과목수를 이수해야 하며  numCourses , 과목번호는 0 순서  대로 되어 있습니다 numCourses-1 . 강좌를  선택하려면   먼저 강좌를 선택  해야prerequisite 함을 나타내는  배열을 얻게 됩니다  .prerequisites[i] = [ai, bi]biai

  • 일부 교과목에는 선수과목이 직접 개설되어 있는데, 예를 들어 한 과목을 수강하고자 할 경우 1 먼저 수강하여야 하며 0 , [0,1] 선수과목의 개수가 짝을 이루는 형태로 부여됩니다.

전제 조건은 간접적 일 수도 있습니다 . 강좌가 a강좌 b의 전제 조건이고 강좌가 강좌의 전제 조건이라면 강좌는 b강좌 의 전제 조건 입니다 .cac

또한  queries .  _ 질의 의 경우 해당 과목이  해당 과목의 선수과목  인지  여부를 답변해야 합니다  .queries[j] = [uj, vj]jujvj

쿼리에 대한 답변이 있는 answer부울 배열을 반환합니다 .answer[j]j

 

예시 1:

입력: numCourses = 2, 전제 조건 = [[1,0]], 쿼리 = [[0,1],[1,0]]
 출력: [false,true]
 설명: 과정 0은 과정 1의 전제 과정이 아닙니다. 단, 1과정은 0과정의 선수과목이다.

예시 2:

입력: numCourses = 2, 전제 조건 = [], 쿼리 = [[1,0],[0,1]]
 출력: [false,false]
 설명: 전제 조건 과정 쌍이 없으므로 각 과정은 독립적입니다.

예시 3:

입력: numCourses = 3, 전제 조건 = [[1,2],[1,0],[2,0]], 쿼리 = [[1,0],[1,2]] 출력: [ true ,
 true ]

 

힌트:

  • 2 <= numCourses <= 100
  • 0 <= prerequisites.length <= (numCourses * (numCourses - 1) / 2)
  • prerequisites[i].length == 2
  • 0 <= ai, bi <= n - 1
  • ai != bi
  • 마다   다르다[ai, bi]
  • 전제조건 다이어그램에는 링이 없습니다.
  • 0 <= ui, vi <= n - 1
  • ui != vi

방법 1: 위상 정렬

우선, 강좌의 순서를 정한다는 점에서 이 문제는 LeetCode 207. Curriculum 과 유사하며 , 이는 위상 정렬을 이용하여 풀 수 있다 .

따라서 문제는 1 0 4 10^4 입니다.1 04개의 쿼리, 각 쿼리를 빠르게 반환하는 방법은 무엇입니까?

우리는 num C ourses × num C ourses numCourses\times numCourses를 생성할 수 있습니다.n u m 강좌 _ _ _×불리언 유형의 배열 n u m C o u rses is Pre isPrei s P reis Pre [ a ] ​​[ b ] isPre[a][b]i s Pre [ a ] ​​​​[ b ]는 코스 aa를 나타냅니다.a가 코스 인지bbb 의 필수과목 . (이런 식으로 특정 쿼리qqq , 그냥 반환은Pre [ q [ 0 ] ] [ q [ 1 ] ] isPre[q[0]][q[1]] 입니다.i s Pre [ q [ 0 ]] [ q [ 1 ]] 수 있음)

토폴로지 정렬에서 thisCourse가 nextCourse의 선수과목으로 판단되면 thisCourse의 선수과목은 모두 nextCourse의 선수과목이 된다 . 수식으로 표현하면 다음과 같습니다.

∀ 0 ≤ i ≤ num Courses , is P re [ i ] [ 다음 C ourse ] ∣ = is P re [ i ] [ this C ourse ] \forall 0\leq i\leq numCourses,\ \ isPre[i][ 다음 강좌]\ \ |=\ isPre[i][이 강좌]∀0n u m 강좌 , _ _  i s Pre [ i ] [ n e x tC o u rse ] _  = i s Pre [ i ] [ 강좌 ] _ _ _ _ _ _

  • 시간 복잡도 O ( num 코스 2 + n + q ) O(numCourses^2 + n + q)O ( 개수 강좌 _ _ _ _ _ _2+N+q ) , 여기서nnn 은 전제 코스 관계 계수,qqq 는 쿼리 수입니다.
  • 공간 복잡성 O ( num 코스 2 + n ) O(numCourses^2 + n)O ( 개수 강좌 _ _ _ _ _ _2+)

AC 코드

C++

class Solution {
    
    
public:
    vector<bool> checkIfPrerequisite(int numCourses, vector<vector<int>>& prerequisites, vector<vector<int>>& queries) {
    
    
        // 建图
        vector<vector<int>> graph(numCourses);
        vector<int> indegree(numCourses);
        for (vector<int>& ab : prerequisites) {
    
    
            graph[ab[0]].push_back(ab[1]);
            indegree[ab[1]]++;
        }

        // 初始化队列
        queue<int> q;
        for (int i = 0; i < numCourses; i++) {
    
    
            if (!indegree[i]) {
    
    
                q.push(i);
            }
        }

        // 预处理(拓扑排序)
        vector<vector<bool>> isPre(numCourses, vector<bool>(numCourses, false));
        while (q.size()) {
    
    
            int thisCourse = q.front();
            q.pop();
            for (int nextCourse : graph[thisCourse]) {
    
    
                indegree[nextCourse]--;
                if (!indegree[nextCourse]) {
    
    
                    q.push(nextCourse);
                }
                isPre[thisCourse][nextCourse] = true;
                for (int i = 0; i < numCourses; i++) {
    
    
                    isPre[i][nextCourse] = isPre[i][nextCourse] | isPre[i][thisCourse];  // vector不支持|=
                }
            }
        }

        // 查询
        vector<bool> ans;
        for (vector<int>& q : queries) {
    
    
            ans.push_back(isPre[q[0]][q[1]]);
        }
        return ans;
    }
};

파이썬

# from typing import List

class Solution:
    def checkIfPrerequisite(self, numCourses: int, prerequisites: List[List[int]], queries: List[List[int]]) -> List[bool]:
        graph = [[] for _ in range(numCourses)]
        indegree = [0] * numCourses
        for a, b in prerequisites:
            graph[a].append(b)
            indegree[b] += 1
        
        q = []
        for i in range(numCourses):
            if not indegree[i]:
                q.append(i)
        
        isPre = [[False for _ in range(numCourses)] for __ in range(numCourses)]
        while q:
            thisCourse = q.pop()
            for nextCourse in graph[thisCourse]:
                indegree[nextCourse] -= 1
                if not indegree[nextCourse]:
                    q.append(nextCourse)
                isPre[thisCourse][nextCourse] = True
                for i in range(numCourses):
                    isPre[i][nextCourse] |= isPre[i][thisCourse]
        
        ans = []
        for a, b in queries:
            ans.append(isPre[a][b])
        return ans

해당 글은 CSDN에 동시에 게재되어 원본이 쉽지 않습니다. 저자의 동의를 받아 재인쇄 후 원문 링크를 첨부해 주세요 ~
Tisfy: https://letmefly.blog.csdn.net/article/details/132825649

추천

출처blog.csdn.net/Tisfy/article/details/132825649