|
56 | 56 |
|
57 | 57 | ## 解法
|
58 | 58 |
|
59 |
| -### 方法一 |
| 59 | +### 方法一:拓扑排序 |
| 60 | + |
| 61 | +拓扑排序的思路是,先统计每个节点的入度,然后从入度为 0 的节点开始,依次删除这些节点,同时更新与这些节点相连的节点的入度,直到所有节点都被删除。 |
| 62 | + |
| 63 | +这里使用队列来存储入度为 0 的节点,每次从队列中取出一个节点,将其加入结果数组中,然后遍历与这个节点相连的节点,将这些节点的入度减 1,如果减 1 后入度为 0,则将这些节点加入队列中。 |
| 64 | + |
| 65 | +最后判断结果数组的长度是否等于节点的个数,如果等于则返回结果数组,否则返回空数组。 |
| 66 | + |
| 67 | +时间复杂度 $O(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是节点的个数和边的个数。 |
60 | 68 |
|
61 | 69 | <!-- tabs:start -->
|
62 | 70 |
|
63 | 71 | ```python
|
64 | 72 | class Solution:
|
65 | 73 | def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
|
66 |
| - g = defaultdict(list) |
| 74 | + g = [[] for _ in range(numCourses)] |
67 | 75 | indeg = [0] * numCourses
|
68 | 76 | for a, b in prerequisites:
|
69 | 77 | g[b].append(a)
|
70 | 78 | indeg[a] += 1
|
71 |
| - q = deque([i for i, v in enumerate(indeg) if v == 0]) |
| 79 | + q = deque(i for i, v in enumerate(indeg) if v == 0) |
72 | 80 | ans = []
|
73 | 81 | while q:
|
74 | 82 | i = q.popleft()
|
@@ -117,23 +125,29 @@ class Solution {
|
117 | 125 | class Solution {
|
118 | 126 | public:
|
119 | 127 | vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
|
120 |
| - vector<vector<int>> g(numCourses); |
| 128 | + vector<int> g[numCourses]; |
121 | 129 | vector<int> indeg(numCourses);
|
122 | 130 | for (auto& p : prerequisites) {
|
123 | 131 | int a = p[0], b = p[1];
|
124 | 132 | g[b].push_back(a);
|
125 | 133 | ++indeg[a];
|
126 | 134 | }
|
127 | 135 | queue<int> q;
|
128 |
| - for (int i = 0; i < numCourses; ++i) |
129 |
| - if (indeg[i] == 0) q.push(i); |
| 136 | + for (int i = 0; i < numCourses; ++i) { |
| 137 | + if (indeg[i] == 0) { |
| 138 | + q.push(i); |
| 139 | + } |
| 140 | + } |
130 | 141 | vector<int> ans;
|
131 |
| - while (!q.empty()) { |
| 142 | + while (q.size()) { |
132 | 143 | int i = q.front();
|
133 | 144 | q.pop();
|
134 | 145 | ans.push_back(i);
|
135 |
| - for (int j : g[i]) |
136 |
| - if (--indeg[j] == 0) q.push(j); |
| 146 | + for (int j : g[i]) { |
| 147 | + if (--indeg[j] == 0) { |
| 148 | + q.push(j); |
| 149 | + } |
| 150 | + } |
137 | 151 | }
|
138 | 152 | return ans.size() == numCourses ? ans : vector<int>();
|
139 | 153 | }
|
@@ -176,61 +190,55 @@ func findOrder(numCourses int, prerequisites [][]int) []int {
|
176 | 190 |
|
177 | 191 | ```ts
|
178 | 192 | function findOrder(numCourses: number, prerequisites: number[][]): number[] {
|
179 |
| - let g = Array.from({ length: numCourses }, () => []); |
180 |
| - let indeg = new Array(numCourses).fill(0); |
181 |
| - for (let [a, b] of prerequisites) { |
| 193 | + const g: number[][] = Array.from({ length: numCourses }, () => []); |
| 194 | + const indeg: number[] = Array(numCourses).fill(0); |
| 195 | + for (const [a, b] of prerequisites) { |
182 | 196 | g[b].push(a);
|
183 | 197 | ++indeg[a];
|
184 | 198 | }
|
185 |
| - let q = []; |
186 |
| - for (let i = 0; i < numCourses; ++i) { |
187 |
| - if (!indeg[i]) { |
188 |
| - q.push(i); |
189 |
| - } |
190 |
| - } |
191 |
| - let ans = []; |
| 199 | + const q: number[] = indeg.map((v, i) => (v === 0 ? i : -1)).filter(v => v !== -1); |
| 200 | + const ans: number[] = []; |
192 | 201 | while (q.length) {
|
193 |
| - const i = q.shift(); |
| 202 | + const i = q.pop()!; |
194 | 203 | ans.push(i);
|
195 |
| - for (let j of g[i]) { |
196 |
| - if (--indeg[j] == 0) { |
| 204 | + for (const j of g[i]) { |
| 205 | + if (--indeg[j] === 0) { |
197 | 206 | q.push(j);
|
198 | 207 | }
|
199 | 208 | }
|
200 | 209 | }
|
201 |
| - return ans.length == numCourses ? ans : []; |
| 210 | + return ans.length === numCourses ? ans : []; |
202 | 211 | }
|
203 | 212 | ```
|
204 | 213 |
|
205 | 214 | ```cs
|
206 | 215 | public class Solution {
|
207 | 216 | public int[] FindOrder(int numCourses, int[][] prerequisites) {
|
208 |
| - var g = new List<int>[numCourses]; |
209 |
| - for (int i = 0; i < numCourses; ++i) |
210 |
| - { |
| 217 | + List<int>[] g = new List<int>[numCourses]; |
| 218 | + for (int i = 0; i < numCourses; i++) { |
211 | 219 | g[i] = new List<int>();
|
212 | 220 | }
|
213 |
| - var indeg = new int[numCourses]; |
214 |
| - foreach (var p in prerequisites) |
215 |
| - { |
| 221 | + int[] indeg = new int[numCourses]; |
| 222 | + foreach (var p in prerequisites) { |
216 | 223 | int a = p[0], b = p[1];
|
217 | 224 | g[b].Add(a);
|
218 | 225 | ++indeg[a];
|
219 | 226 | }
|
220 |
| - var q = new Queue<int>(); |
221 |
| - for (int i = 0; i < numCourses; ++i) |
222 |
| - { |
223 |
| - if (indeg[i] == 0) q.Enqueue(i); |
| 227 | + Queue<int> q = new Queue<int>(); |
| 228 | + for (int i = 0; i < numCourses; ++i) { |
| 229 | + if (indeg[i] == 0) { |
| 230 | + q.Enqueue(i); |
| 231 | + } |
224 | 232 | }
|
225 |
| - var ans = new int[numCourses]; |
226 |
| - var cnt = 0; |
227 |
| - while (q.Count > 0) |
228 |
| - { |
| 233 | + int[] ans = new int[numCourses]; |
| 234 | + int cnt = 0; |
| 235 | + while (q.Count > 0) { |
229 | 236 | int i = q.Dequeue();
|
230 | 237 | ans[cnt++] = i;
|
231 |
| - foreach (int j in g[i]) |
232 |
| - { |
233 |
| - if (--indeg[j] == 0) q.Enqueue(j); |
| 238 | + foreach (int j in g[i]) { |
| 239 | + if (--indeg[j] == 0) { |
| 240 | + q.Enqueue(j); |
| 241 | + } |
234 | 242 | }
|
235 | 243 | }
|
236 | 244 | return cnt == numCourses ? ans : new int[0];
|
|
0 commit comments