# 1203. Sort Items by Groups Respecting Dependencies

• Time: $O(|V| + |E|)$, where $|V| = n + m$ and $|E| = |\texttt{group[i]}| \ne -1 + |\texttt{items[i]}| \in \texttt{beforeItems}$
• Space: $O(|V| + |E|)$
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 class Solution { public: vector sortItems(int n, int m, vector& group, vector>& beforeItems) { vector> graph(n + m); vector inDegree(n + m); // Build graph by remapping k-th group to k + n imaginary node for (int i = 0; i < group.size(); ++i) { if (group[i] == -1) continue; graph[group[i] + n].push_back(i); ++inDegree[i]; } for (int i = 0; i < beforeItems.size(); ++i) for (const int b : beforeItems[i]) { const int u = group[b] == -1 ? b : group[b] + n; const int v = group[i] == -1 ? i : group[i] + n; if (u == v) { // Already in the same group graph[b].push_back(i); ++inDegree[i]; } else { graph[u].push_back(v); ++inDegree[v]; } } // Topology vector ans; for (int i = 0; i < n + m; ++i) if (inDegree[i] == 0) // inDegree[i] == -1 means visited dfs(graph, i, inDegree, n, ans); return ans.size() == n ? ans : vector(); } private: void dfs(const vector>& graph, int u, vector& inDegree, int n, vector& ans) { if (u < n) ans.push_back(u); inDegree[u] = -1; // Mark as visited for (const int v : graph[u]) if (--inDegree[v] == 0) dfs(graph, v, inDegree, n, ans); } }; 
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Solution { public int[] sortItems(int n, int m, int[] group, List> beforeItems) { List[] graph = new List[n + m]; int[] inDegree = new int[n + m]; for (int i = 0; i < graph.length; ++i) graph[i] = new ArrayList<>(); // Build graph by remapping k-th group to k + n imaginary node for (int i = 0; i < group.length; ++i) { if (group[i] == -1) continue; graph[group[i] + n].add(i); ++inDegree[i]; } for (int i = 0; i < beforeItems.size(); ++i) for (final int b : beforeItems.get(i)) { final int u = group[b] == -1 ? b : group[b] + n; final int v = group[i] == -1 ? i : group[i] + n; if (u == v) { // Already in the same group graph[b].add(i); ++inDegree[i]; } else { graph[u].add(v); ++inDegree[v]; } } // Topology List ans = new ArrayList<>(); for (int i = 0; i < n + m; ++i) if (inDegree[i] == 0) // inDegree[i] == -1 means visited dfs(graph, i, inDegree, n, ans); return ans.size() == n ? ans.stream().mapToInt(Integer::intValue).toArray() : new int[] {}; } private void dfs(List[] graph, int u, int[] inDegree, int n, List ans) { if (u < n) ans.add(u); inDegree[u] = -1; // Mark as visited for (final int v : graph[u]) if (--inDegree[v] == 0) dfs(graph, v, inDegree, n, ans); } }