{"id":276,"date":"2025-06-09T18:54:11","date_gmt":"2025-06-09T13:24:11","guid":{"rendered":"https:\/\/codeanddebug.in\/blog\/?p=276"},"modified":"2025-06-09T18:54:12","modified_gmt":"2025-06-09T13:24:12","slug":"course-schedule-1","status":"publish","type":"post","link":"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/","title":{"rendered":"Course Schedule | Leetcode 207 | Kahn\u2019s Algorithm Walk-through in Python"},"content":{"rendered":"\n<p>Check if you can finish every course when some need to be done first. We build the course graph, run Kahn\u2019s BFS topological sort, and detect cycles. Step-by-step intuition, detailed code explanation, dry run, and Big-O analysis.<\/p>\n\n\n\n<p>Here&#8217;s the [<strong><a href=\"https:\/\/leetcode.com\/problems\/course-schedule\/\" target=\"_blank\" rel=\"noreferrer noopener\"><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\"><span style=\"text-decoration: underline;\">Problem Link<\/span><\/mark><\/a><\/strong>] to begin with.<\/p>\n\n\n<div style=\"max-width: -moz-fit-content; \" class=\"wp-block-ub-table-of-contents-block ub_table-of-contents ub_table-of-contents-collapsed\" id=\"ub_table-of-contents-614187f8-0c70-440d-9d1e-036a940e963f\" data-linktodivider=\"false\" data-showtext=\"show\" data-hidetext=\"hide\" data-scrolltype=\"auto\" data-enablesmoothscroll=\"true\" data-initiallyhideonmobile=\"false\" data-initiallyshow=\"false\"><div class=\"ub_table-of-contents-header-container\" style=\"\">\n\t\t\t<div class=\"ub_table-of-contents-header\" style=\"text-align: left; \">\n\t\t\t\t<div class=\"ub_table-of-contents-title\">Contents:<\/div>\n\t\t\t\t<div class=\"ub_table-of-contents-header-toggle\">\n\t\t\t<div class=\"ub_table-of-contents-toggle\" style=\"\">\n\t\t\t\u00a0[<a class=\"ub_table-of-contents-toggle-link\" href=\"#\" style=\"\">show<\/a>]\n\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div><div class=\"ub_table-of-contents-extra-container\" style=\"\">\n\t\t\t<div class=\"ub_table-of-contents-container ub_table-of-contents-1-column ub-hide\">\n\t\t\t\t<ul style=\"\"><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#0-1-what-does-the-problem-ask\" style=\"\">1. What does the problem ask?<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#1-2-quick-examples\" style=\"\">2. Quick examples<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#2-3-ntuition-amp-approach-trainer-style\" style=\"\">3. ntuition &amp; Approach (trainer style)<\/a><ul><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#3-31-turning-courses-into-a-graph\" style=\"\">3.1 Turning courses into a graph<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#4-32-what-keeps-us-from-finishing\" style=\"\">3.2 What keeps us from finishing?<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#5-33-kahn%E2%80%99s-algorithm-in-plain-words\" style=\"\">3.3 Kahn\u2019s algorithm in plain words<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#6-34-why-it-works\" style=\"\">3.4 Why it works<\/a><\/li><\/ul><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#7-4-code\" style=\"\">4. Code<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#8-5-step-by-step-code-explanation\" style=\"\">5. Step-by-step code explanation<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#9-6-dry-run-on-a-tricky-case\" style=\"\">6. Dry run on a tricky case<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#10-7-complexity\" style=\"\">7. Complexity<\/a><\/li><li style=\"\"><a href=\"https:\/\/codeanddebug.in\/blog\/course-schedule-1\/#11-8-conclusion\" style=\"\">8. Conclusion<\/a><\/li><\/ul>\n\t\t\t<\/div>\n\t\t<\/div><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"0-1-what-does-the-problem-ask\">1. What does the problem ask?<\/h2>\n\n\n\n<p>You have <code>numCourses<\/code> labeled <code>0 \u2026 numCourses \u2212 1<\/code>.<br>Each pair <code>[a, b]<\/code> in <code>prerequisites<\/code> means:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Take course <code>b<\/code> before course <code>a<\/code>.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p>Return <strong><code>True<\/code><\/strong> if you can take all courses in some order.<br>Return <strong><code>False<\/code><\/strong> if the rules create a cycle that blocks progress.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"1-2-quick-examples\">2. Quick examples<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><code>numCourses<\/code><\/th><th><code>prerequisites<\/code><\/th><th>Result<\/th><th>Why<\/th><\/tr><\/thead><tbody><tr><td><code>2<\/code><\/td><td><code>[[1, 0]]<\/code><\/td><td><code>True<\/code><\/td><td>Take <strong>0<\/strong> \u279c then <strong>1<\/strong>.<\/td><\/tr><tr><td><code>2<\/code><\/td><td><code>[[1, 0], [0, 1]]<\/code><\/td><td><code>False<\/code><\/td><td>0 needs 1 and 1 needs 0 \u2192 cycle.<\/td><\/tr><tr><td><code>4<\/code><\/td><td><code>[[1,0],[2,0],[3,1],[3,2]]<\/code><\/td><td><code>True<\/code><\/td><td>0 \u279c (1,2) \u279c 3.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Also check <a href=\"https:\/\/codeanddebug.in\/blog\/detect-cycle-in-a-directed-graph-kahns-algorithm-bfs\/\" data-type=\"post\" data-id=\"262\" target=\"_blank\" rel=\"noreferrer noopener\"><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-purple-color\"><strong>Detect Cycle in a Directed Graph \u2013 Kahn\u2019s Algorithm<\/strong><\/mark><\/a><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"2-3-ntuition-amp-approach-trainer-style\">3. Intuition &amp; Approach (trainer style)<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"3-31-turning-courses-into-a-graph\">3.1 Turning courses into a graph<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Think of every course as a <strong>node<\/strong>.<\/li>\n\n\n\n<li>A rule \u201c<code>b<\/code> before <code>a<\/code>\u201d is drawn as a <strong>directed edge<\/strong> from <strong><code>a<\/code> to <code>b<\/code><\/strong> in our code.<br><em>Why this direction?<\/em> We will remove a course <strong>after<\/strong> all arrows leaving it are handled (more on that soon).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"4-32-what-keeps-us-from-finishing\">3.2 What keeps us from finishing?<\/h3>\n\n\n\n<p>A <strong>cycle<\/strong> like <code>0 \u2192 1 \u2192 2 \u2192 0<\/code>.<br>Inside a cycle no course can be done first because each one waits for another in the loop.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"5-33-kahn%E2%80%99s-algorithm-in-plain-words\">3.3 Kahn\u2019s algorithm in plain words<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Indegree = number of incoming edges.<\/strong><br><em>For us<\/em>: how many other courses still depend on this course.<\/li>\n\n\n\n<li><strong>Start queue with every course whose indegree is 0.<\/strong><br>Those courses have nobody waiting on them (in our edge direction) so we can safely \u201ctake\u201d them now.<\/li>\n\n\n\n<li><strong>Process the queue until empty.<\/strong>\n<ul class=\"wp-block-list\">\n<li>Pop a course, mark it as finished.<\/li>\n\n\n\n<li>For every arrow that leaves it, lower the neighbour\u2019s indegree.<\/li>\n\n\n\n<li>If a neighbour\u2019s indegree drops to 0, it is now free to take \u2192 push it into the queue.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>After BFS ends:<\/strong>\n<ul class=\"wp-block-list\">\n<li>If we finished <strong>all<\/strong> courses \u2192 <strong>no cycle<\/strong> \u2192 return <code>True<\/code>.<\/li>\n\n\n\n<li>If some courses were never freed (queue never reached them) \u2192 <strong>cycle exists<\/strong> \u2192 return <code>False<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"6-34-why-it-works\">3.4 Why it works<\/h3>\n\n\n\n<p>Removing zero-indegree nodes layer by layer mimics deleting arrows.<br>If a cycle exists, its nodes can never reach indegree 0, so they never enter the queue.<br>The size of the \u201cfinished\u201d list therefore tells us instantly whether a cycle was present.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"7-4-code\">4. Code<\/h2>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"from collections import deque\n\n\nclass Solution:\n    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -&gt; bool:\n        # Build adjacency list and indegree array\n        adj_list = [[] for _ in range(numCourses)]\n        indegrees = [0 for _ in range(numCourses)]\n\n        for u, v in prerequisites:  # edge: u depends on v\n            adj_list[u].append(v)   # arrow u \u2192 v\n            indegrees[v] += 1       # v has one more incoming edge\n\n        # Collect all starting courses (indegree 0)\n        queue = deque()\n        result = []                 # keeps the order we &quot;finish&quot; courses\n        for i in range(numCourses):\n            if indegrees[i] == 0:\n                queue.append(i)\n\n        # Kahn's BFS\n        while len(queue) != 0:\n            current_node = queue.popleft()  # course ready to finish\n            result.append(current_node)\n            for adjNode in adj_list[current_node]:  # courses it points to\n                indegrees[adjNode] -= 1             # remove the edge\n                if indegrees[adjNode] == 0:         # neighbour now free\n                    queue.append(adjNode)\n\n        # If we finished every course, schedule is possible\n        if len(result) == numCourses:\n            return True\n        return False\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">from<\/span><span style=\"color: #D4D4D4\"> collections <\/span><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> deque<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Solution<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">def<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">canFinish<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">self<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">numCourses<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #4EC9B0\">int<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">prerequisites<\/span><span style=\"color: #D4D4D4\">: List[List[<\/span><span style=\"color: #4EC9B0\">int<\/span><span style=\"color: #D4D4D4\">]]) -&gt; <\/span><span style=\"color: #4EC9B0\">bool<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\"># Build adjacency list and indegree array<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        adj_list = [[] <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> _ <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">range<\/span><span style=\"color: #D4D4D4\">(numCourses)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        indegrees = [<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> _ <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">range<\/span><span style=\"color: #D4D4D4\">(numCourses)]<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> u, v <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> prerequisites:  <\/span><span style=\"color: #6A9955\"># edge: u depends on v<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            adj_list[u].append(v)   <\/span><span style=\"color: #6A9955\"># arrow u \u2192 v<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            indegrees[v] += <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">       <\/span><span style=\"color: #6A9955\"># v has one more incoming edge<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\"># Collect all starting courses (indegree 0)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        queue = deque()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        result = []                 <\/span><span style=\"color: #6A9955\"># keeps the order we &quot;finish&quot; courses<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> i <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">range<\/span><span style=\"color: #D4D4D4\">(numCourses):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> indegrees[i] == <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                queue.append(i)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\"># Kahn&#39;s BFS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">while<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">len<\/span><span style=\"color: #D4D4D4\">(queue) != <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            current_node = queue.popleft()  <\/span><span style=\"color: #6A9955\"># course ready to finish<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            result.append(current_node)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">for<\/span><span style=\"color: #D4D4D4\"> adjNode <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> adj_list[current_node]:  <\/span><span style=\"color: #6A9955\"># courses it points to<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                indegrees[adjNode] -= <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #6A9955\"># remove the edge<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> indegrees[adjNode] == <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">:         <\/span><span style=\"color: #6A9955\"># neighbour now free<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    queue.append(adjNode)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\"># If we finished every course, schedule is possible<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">len<\/span><span style=\"color: #D4D4D4\">(result) == numCourses:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">True<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">False<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"8-5-step-by-step-code-explanation\">5. Step-by-step code explanation<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Lines 5\u20138<\/strong> \u2013 We create two helpers:\n<ul class=\"wp-block-list\">\n<li><code>adj_list[u]<\/code> \u2192 list of courses that <code>u<\/code> points to (its prerequisites in our chosen direction).<\/li>\n\n\n\n<li><code>indegrees[v]<\/code> \u2192 how many arrows point <strong>into<\/strong> course <code>v<\/code>.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Lines 10\u201312<\/strong> \u2013 For every rule <code>[u, v]<\/code> we:\n<ul class=\"wp-block-list\">\n<li>Add <code>v<\/code> into <code>u<\/code>\u2019s list.<\/li>\n\n\n\n<li>Increment <code>v<\/code>\u2019s indegree.<\/li>\n\n\n\n<li>Now <code>v<\/code> \u201cwaits\u201d for one more course before it can be freed.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Lines 15\u201318<\/strong> \u2013 Fill the queue with all courses whose indegree is zero:<br>They are the ones that no other course depends on, so we finish them first.<\/li>\n\n\n\n<li><strong>Lines 21\u201327<\/strong> \u2013 Main BFS loop:\n<ul class=\"wp-block-list\">\n<li>Pop a course <code>current_node<\/code> and append it to <code>result<\/code> (meaning we completed it).<\/li>\n\n\n\n<li>Visit every neighbour <code>adjNode<\/code>.<\/li>\n\n\n\n<li>Decrease that neighbour\u2019s indegree because one dependency disappeared.<\/li>\n\n\n\n<li>As soon as a neighbour\u2019s indegree becomes 0, push it to the queue\u2014<br>it is now free to complete in a later round.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Lines 29\u201332<\/strong> \u2013 After the queue empties:\n<ul class=\"wp-block-list\">\n<li>If we completed <code>numCourses<\/code> courses, no cycle existed \u2192 return <code>True<\/code>.<\/li>\n\n\n\n<li>Otherwise at least one course was stuck in a cycle \u2192 return <code>False<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"9-6-dry-run-on-a-tricky-case\">6. Dry run on a tricky case<\/h2>\n\n\n\n<p><code>numCourses = 4<\/code>, <code>prerequisites = [[1,0],[2,0],[3,1],[3,2]]<\/code><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Phase<\/th><th>Queue<\/th><th><code>indegrees<\/code><\/th><th><code>result<\/code><\/th><th>Explanation<\/th><\/tr><\/thead><tbody><tr><td>Build<\/td><td>\u2013<\/td><td><code>[2,1,1,0]<\/code><\/td><td>\u2013<\/td><td>0 has 2 incoming, 3 has 0<\/td><\/tr><tr><td>Init<\/td><td><code>[3]<\/code><\/td><td>same<\/td><td><code>[]<\/code><\/td><td>only course 3 has indegree 0<\/td><\/tr><tr><td>Pop 3<\/td><td><code>[]<\/code><\/td><td><code>[1,1,1,0]<\/code><\/td><td><code>[3]<\/code><\/td><td>remove edges 3\u21921 and 3\u21922<\/td><\/tr><tr><td>Both 1 &amp; 2 still &gt;0<\/td><td><code>[]<\/code><\/td><td>\u2013<\/td><td>\u2013<\/td><td>queue empty! Wait\u2026<\/td><\/tr><tr><td>We finished 1 course &lt; 4<\/td><td>\u2013<\/td><td>\u2013<\/td><td><code>[3]<\/code><\/td><td><strong>Return <code>False<\/code><\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>So here the algorithm shows a cycle, which is correct because 0 \u2194 (1 and 2) forms a deadlock.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"10-7-complexity\">7. Complexity<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Measure<\/th><th>Value<\/th><th>Why<\/th><\/tr><\/thead><tbody><tr><td><strong>Time<\/strong><\/td><td><strong>O(V + E)<\/strong><\/td><td>Build structures + visit each edge once.<\/td><\/tr><tr><td><strong>Space<\/strong><\/td><td><strong>O(V + E)<\/strong><\/td><td>Adjacency list (<code>E<\/code>), indegree array and queue (<code>V<\/code>).<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><code>V = numCourses<\/code>, <code>E = len(prerequisites)<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"11-8-conclusion\">8. Conclusion<\/h2>\n\n\n\n<p>By viewing courses and prerequisites as a graph and repeatedly removing nodes with zero indegree (Kahn\u2019s BFS topological sort), we can:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Detect cycles<\/strong> (impossible schedules) quickly.<\/li>\n\n\n\n<li><strong>Build a valid course order<\/strong> when possible (just read the <code>result<\/code> list).<\/li>\n<\/ul>\n\n\n\n<p>This approach is linear, easy to code, and mirrors how real-world scheduling systems handle dependencies.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-16018d1d wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.codeanddebug.in\/course\/zero-to-hero-python-dsa\">Join our Advance DSA COURSE<\/a><\/div>\n<\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><em>For any changes to the article, kindly email at <a href=\"mailto:code@codeanddebug.in\">code@codeanddebug.in<\/a> or contact us at <a href=\"tel:+91-9712928220\">+91-9712928220<\/a>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Check if you can finish every course when some need to be done first. We build the course graph, run Kahn\u2019s BFS topological sort, and detect cycles. Step-by-step intuition, detailed code explanation, dry run, and Big-O analysis. Here&#8217;s the [Problem Link] to begin with. 1. What does the problem ask? You have numCourses labeled 0<\/p>\n","protected":false},"author":1,"featured_media":277,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ub_ctt_via":"","footnotes":""},"categories":[3,6],"tags":[21,17,19],"class_list":{"0":"post-276","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-data-structures-and-algorithm","8":"category-intermediate","9":"tag-bfs","10":"tag-graph","11":"tag-medium"},"featured_image_src":"https:\/\/codeanddebug.in\/blog\/wp-content\/uploads\/2025\/06\/course-schedule-1-featured-image.png","author_info":{"display_name":"codeanddebug","author_link":"https:\/\/codeanddebug.in\/blog\/author\/codeanddebug\/"},"_links":{"self":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/276","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/comments?post=276"}],"version-history":[{"count":2,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/276\/revisions"}],"predecessor-version":[{"id":286,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/posts\/276\/revisions\/286"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/media\/277"}],"wp:attachment":[{"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/media?parent=276"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/categories?post=276"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codeanddebug.in\/blog\/wp-json\/wp\/v2\/tags?post=276"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}