Skip to content

Commit 461e6ad

Browse files
committed
feat: add solutions to lc problem: No.1203
No.1203.Sort Items by Groups Respecting Dependencies
1 parent dbcdaea commit 461e6ad

File tree

7 files changed

+981
-0
lines changed

7 files changed

+981
-0
lines changed

solution/1200-1299/1203.Sort Items by Groups Respecting Dependencies/README.md

Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,360 @@
5454

5555
<!-- 这里可写通用的实现逻辑 -->
5656

57+
**方法一:拓扑排序**
58+
59+
我们先遍历数组 $group$,对于每个项目,如果其不属于任何小组,则将其新建一个小组,编号为 $m$,并将 $m$ 的值加一。这样我们就能保证所有项目都属于某个小组了。然后,我们用一个数组 $groupItems$ 记录每个小组包含的项目,数组下标为小组编号,数组值为包含的项目列表。
60+
61+
接下来,我们需要建图。对于每个项目,我们需要建立两种图,一种是项目间的图,一种是小组间的图。我们遍历数组 $group$,对于当前项目 $i$,它所在的小组为 $group[i]$,我们遍历 $beforeItems[i]$,对于其中的每个项目 $j$,如果 $group[i] = group[j]$,说明 $i$ 和 $j$ 属于同一小组,我们在项目图中添加一条 $j \to i$ 的边,否则说明 $i$ 和 $j$ 属于不同的小组,我们在小组间的图中添加一条 $group[j] \to group[i]$ 的边,并且更新对应的入度数组。
62+
63+
接下来,我们先对小组间的图进行拓扑排序,得到排序后的小组列表 $groupOrder$,如果排序后的列表长度不等于小组总数,说明无法完成排序,返回空列表。否则,我们遍历 $groupOrder$,对于其中的每个小组 $gi$,我们将该小组包含的项目列表 $groupItems[gi]$ 进行拓扑排序,得到排序后的项目列表 $itemOrder$,如果排序后的列表长度不等于该小组包含的项目总数,说明无法完成排序,返回空列表。否则,我们将 $itemOrder$ 中的项目加入答案数组中,最终返回该答案数组即可。
64+
65+
时间复杂度 $O(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是项目总数和小组总数。
66+
5767
<!-- tabs:start -->
5868

5969
### **Python3**
6070

6171
<!-- 这里可写当前语言的特殊实现逻辑 -->
6272

6373
```python
74+
class Solution:
75+
def sortItems(
76+
self, n: int, m: int, group: List[int], beforeItems: List[List[int]]
77+
) -> List[int]:
78+
def topo_sort(degree, graph, items):
79+
q = deque(i for _, i in enumerate(items) if degree[i] == 0)
80+
res = []
81+
while q:
82+
i = q.popleft()
83+
res.append(i)
84+
for j in graph[i]:
85+
degree[j] -= 1
86+
if degree[j] == 0:
87+
q.append(j)
88+
return res if len(res) == len(items) else []
89+
90+
idx = m
91+
group_items = [[] for _ in range(n + m)]
92+
for i, g in enumerate(group):
93+
if g == -1:
94+
group[i] = idx
95+
idx += 1
96+
group_items[group[i]].append(i)
6497

98+
item_degree = [0] * n
99+
group_degree = [0] * (n + m)
100+
item_graph = [[] for _ in range(n)]
101+
group_graph = [[] for _ in range(n + m)]
102+
for i, gi in enumerate(group):
103+
for j in beforeItems[i]:
104+
gj = group[j]
105+
if gi == gj:
106+
item_degree[i] += 1
107+
item_graph[j].append(i)
108+
else:
109+
group_degree[gi] += 1
110+
group_graph[gj].append(gi)
111+
112+
group_order = topo_sort(group_degree, group_graph, range(n + m))
113+
if not group_order:
114+
return []
115+
ans = []
116+
for gi in group_order:
117+
items = group_items[gi]
118+
item_order = topo_sort(item_degree, item_graph, items)
119+
if len(items) != len(item_order):
120+
return []
121+
ans.extend(item_order)
122+
return ans
65123
```
66124

67125
### **Java**
68126

69127
<!-- 这里可写当前语言的特殊实现逻辑 -->
70128

71129
```java
130+
class Solution {
131+
public int[] sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
132+
int idx = m;
133+
List<Integer>[] groupItems = new List[n + m];
134+
int[] itemDegree = new int[n];
135+
int[] groupDegree = new int[n + m];
136+
List<Integer>[] itemGraph = new List[n];
137+
List<Integer>[] groupGraph = new List[n + m];
138+
Arrays.setAll(groupItems, k -> new ArrayList<>());
139+
Arrays.setAll(itemGraph, k -> new ArrayList<>());
140+
Arrays.setAll(groupGraph, k -> new ArrayList<>());
141+
for (int i = 0; i < n; ++i) {
142+
if (group[i] == -1) {
143+
group[i] = idx++;
144+
}
145+
groupItems[group[i]].add(i);
146+
}
147+
for (int i = 0; i < n; ++i) {
148+
for (int j : beforeItems.get(i)) {
149+
if (group[i] == group[j]) {
150+
++itemDegree[i];
151+
itemGraph[j].add(i);
152+
} else {
153+
++groupDegree[group[i]];
154+
groupGraph[group[j]].add(group[i]);
155+
}
156+
}
157+
}
158+
List<Integer> items = new ArrayList<>();
159+
for (int i = 0; i < n + m; ++i) {
160+
items.add(i);
161+
}
162+
var groupOrder = topoSort(groupDegree, groupGraph, items);
163+
if (groupOrder.isEmpty()) {
164+
return new int[0];
165+
}
166+
List<Integer> ans = new ArrayList<>();
167+
for (int gi : groupOrder) {
168+
items = groupItems[gi];
169+
var itemOrder = topoSort(itemDegree, itemGraph, items);
170+
if (itemOrder.size() != items.size()) {
171+
return new int[0];
172+
}
173+
ans.addAll(itemOrder);
174+
}
175+
return ans.stream().mapToInt(Integer::intValue).toArray();
176+
}
177+
178+
private List<Integer> topoSort(int[] degree, List<Integer>[] graph, List<Integer> items) {
179+
Deque<Integer> q = new ArrayDeque<>();
180+
for (int i : items) {
181+
if (degree[i] == 0) {
182+
q.offer(i);
183+
}
184+
}
185+
List<Integer> ans = new ArrayList<>();
186+
while (!q.isEmpty()) {
187+
int i = q.poll();
188+
ans.add(i);
189+
for (int j : graph[i]) {
190+
if (--degree[j] == 0) {
191+
q.offer(j);
192+
}
193+
}
194+
}
195+
return ans.size() == items.size() ? ans : List.of();
196+
}
197+
}
198+
```
199+
200+
### **C++**
201+
202+
```cpp
203+
class Solution {
204+
public:
205+
vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems) {
206+
int idx = m;
207+
vector<vector<int>> groupItems(n + m);
208+
vector<int> itemDegree(n);
209+
vector<int> groupDegree(n + m);
210+
vector<vector<int>> itemGraph(n);
211+
vector<vector<int>> groupGraph(n + m);
212+
for (int i = 0; i < n; ++i) {
213+
if (group[i] == -1) {
214+
group[i] = idx++;
215+
}
216+
groupItems[group[i]].push_back(i);
217+
}
218+
for (int i = 0; i < n; ++i) {
219+
for (int j : beforeItems[i]) {
220+
if (group[i] == group[j]) {
221+
++itemDegree[i];
222+
itemGraph[j].push_back(i);
223+
} else {
224+
++groupDegree[group[i]];
225+
groupGraph[group[j]].push_back(group[i]);
226+
}
227+
}
228+
}
229+
vector<int> items(n + m);
230+
iota(items.begin(), items.end(), 0);
231+
auto topoSort = [](vector<vector<int>>& graph, vector<int>& degree, vector<int>& items) -> vector<int> {
232+
queue<int> q;
233+
for (int& i : items) {
234+
if (degree[i] == 0) {
235+
q.push(i);
236+
}
237+
}
238+
vector<int> ans;
239+
while (!q.empty()) {
240+
int i = q.front();
241+
q.pop();
242+
ans.push_back(i);
243+
for (int& j : graph[i]) {
244+
if (--degree[j] == 0) {
245+
q.push(j);
246+
}
247+
}
248+
}
249+
return ans.size() == items.size() ? ans : vector<int>();
250+
};
251+
auto groupOrder = topoSort(groupGraph, groupDegree, items);
252+
if (groupOrder.empty()) {
253+
return vector<int>();
254+
}
255+
vector<int> ans;
256+
for (int& gi : groupOrder) {
257+
items = groupItems[gi];
258+
auto itemOrder = topoSort(itemGraph, itemDegree, items);
259+
if (items.size() != itemOrder.size()) {
260+
return vector<int>();
261+
}
262+
ans.insert(ans.end(), itemOrder.begin(), itemOrder.end());
263+
}
264+
return ans;
265+
}
266+
};
267+
```
268+
269+
### **Go**
270+
271+
```go
272+
func sortItems(n int, m int, group []int, beforeItems [][]int) []int {
273+
idx := m
274+
groupItems := make([][]int, n+m)
275+
itemDegree := make([]int, n)
276+
groupDegree := make([]int, n+m)
277+
itemGraph := make([][]int, n)
278+
groupGraph := make([][]int, n+m)
279+
for i, g := range group {
280+
if g == -1 {
281+
group[i] = idx
282+
idx++
283+
}
284+
groupItems[group[i]] = append(groupItems[group[i]], i)
285+
}
286+
for i, gi := range group {
287+
for _, j := range beforeItems[i] {
288+
gj := group[j]
289+
if gi == gj {
290+
itemDegree[i]++
291+
itemGraph[j] = append(itemGraph[j], i)
292+
} else {
293+
groupDegree[gi]++
294+
groupGraph[gj] = append(groupGraph[gj], gi)
295+
}
296+
}
297+
}
298+
items := make([]int, n+m)
299+
for i := range items {
300+
items[i] = i
301+
}
302+
topoSort := func(degree []int, graph [][]int, items []int) []int {
303+
q := []int{}
304+
for _, i := range items {
305+
if degree[i] == 0 {
306+
q = append(q, i)
307+
}
308+
}
309+
ans := []int{}
310+
for len(q) > 0 {
311+
i := q[0]
312+
q = q[1:]
313+
ans = append(ans, i)
314+
for _, j := range graph[i] {
315+
degree[j]--
316+
if degree[j] == 0 {
317+
q = append(q, j)
318+
}
319+
}
320+
}
321+
return ans
322+
}
323+
groupOrder := topoSort(groupDegree, groupGraph, items)
324+
if len(groupOrder) != len(items) {
325+
return nil
326+
}
327+
ans := []int{}
328+
for _, gi := range groupOrder {
329+
items = groupItems[gi]
330+
itemOrder := topoSort(itemDegree, itemGraph, items)
331+
if len(items) != len(itemOrder) {
332+
return nil
333+
}
334+
ans = append(ans, itemOrder...)
335+
}
336+
return ans
337+
}
338+
```
339+
340+
### **TypeScript**
72341

342+
```ts
343+
function sortItems(
344+
n: number,
345+
m: number,
346+
group: number[],
347+
beforeItems: number[][],
348+
): number[] {
349+
let idx = m;
350+
const groupItems: number[][] = new Array(n + m).fill(0).map(() => []);
351+
const itemDegree: number[] = new Array(n).fill(0);
352+
const gorupDegree: number[] = new Array(n + m).fill(0);
353+
const itemGraph: number[][] = new Array(n).fill(0).map(() => []);
354+
const groupGraph: number[][] = new Array(n + m).fill(0).map(() => []);
355+
for (let i = 0; i < n; ++i) {
356+
if (group[i] === -1) {
357+
group[i] = idx++;
358+
}
359+
groupItems[group[i]].push(i);
360+
}
361+
for (let i = 0; i < n; ++i) {
362+
for (const j of beforeItems[i]) {
363+
if (group[i] === group[j]) {
364+
++itemDegree[i];
365+
itemGraph[j].push(i);
366+
} else {
367+
++gorupDegree[group[i]];
368+
groupGraph[group[j]].push(group[i]);
369+
}
370+
}
371+
}
372+
let items = new Array(n + m).fill(0).map((_, i) => i);
373+
const topoSort = (
374+
graph: number[][],
375+
degree: number[],
376+
items: number[],
377+
): number[] => {
378+
const q: number[] = [];
379+
for (const i of items) {
380+
if (degree[i] === 0) {
381+
q.push(i);
382+
}
383+
}
384+
const ans: number[] = [];
385+
while (q.length) {
386+
const i = q.pop()!;
387+
ans.push(i);
388+
for (const j of graph[i]) {
389+
if (--degree[j] === 0) {
390+
q.push(j);
391+
}
392+
}
393+
}
394+
return ans.length === items.length ? ans : [];
395+
};
396+
const groupOrder = topoSort(groupGraph, gorupDegree, items);
397+
if (groupOrder.length === 0) {
398+
return [];
399+
}
400+
const ans: number[] = [];
401+
for (const gi of groupOrder) {
402+
items = groupItems[gi];
403+
const itemOrder = topoSort(itemGraph, itemDegree, items);
404+
if (itemOrder.length !== items.length) {
405+
return [];
406+
}
407+
ans.push(...itemOrder);
408+
}
409+
return ans;
410+
}
73411
```
74412

75413
### **...**

0 commit comments

Comments
 (0)