Pattern · Tìm kiếm theo chiều sâuTrung bình
Lịch Học MônCourse Schedule
Hiểu bài
Có numCourses môn học (đánh số 0 đến numCourses-1). Mảng prerequisites gồm các cặp [a, b] nghĩa là phải học b trước a. Hỏi có thể hoàn thành tất cả môn không?
Ví dụ:
ts
numCourses = 2, prerequisites = [[1,0]]
output = true // học 0 trước rồi học 1
numCourses = 2, prerequisites = [[1,0],[0,1]]
output = false // 0 cần 1, 1 cần 0 — chu trình!Bài toán rút gọn thành: đồ thị có hướng prerequisites có chu trình không? Nếu có chu trình → không thể hoàn thành.
Nếu không → có thứ tự topo hợp lệ.
Cách cơ bản
O(V + E) time, O(V + E) spacets
// Kahn's BFS (Topological Sort) — trực quan hơn với in-degree
function canFinishBFS(numCourses: number, prerequisites: number[][]): boolean {
const inDegree = new Array(numCourses).fill(0)
const adj: number[][] = Array.from({ length: numCourses }, () => [])
for (const [a, b] of prerequisites) {
adj[b].push(a)
inDegree[a]++
}
const queue: number[] = []
for (let i = 0; i < numCourses; i++) {
if (inDegree[i] === 0) queue.push(i)
}
let processed = 0
while (queue.length > 0) {
const node = queue.shift()!
processed++
for (const next of adj[node]) {
inDegree[next]--
if (inDegree[next] === 0) queue.push(next)
}
}
return processed === numCourses
}Vì sao cách này chậm:
Kahn's BFS dùng in-degree để phát hiện chu trình: nếu sau khi xử lý hết các nút in-degree=0 mà vẫn còn nút chưa xử lý → có chu trình.
- Đây là cách brute force có thể chấp nhận, nhưng DFS với trạng thái 3 màu thường được hỏi hơn.
- Lưu ý mảng in-degree được khởi tạo bằng 0 cho mọi nút.
Mở khoá để xem lời giải tối ưu, chạy thử từng bước và câu hỏi liên quan
Xem đầy đủ chạy thử từng bước, Big-O, trường hợp biên và biến thể công ty Việt Nam.