想法:利用 Topological Sort + BFS, 首先我們需要找出同一 group 內的 item 順序, 然後再找出不同 group 之間的順序, 最後遍歷 group 順序和 group 內的 item 順序即可。需要注意的是, group[i] == -1 的 items 並不屬於同一個 group, 不必滿足相鄰條件, 因此我們要對那些 group[i] == -1 的 items 重新編號, 讓他們每個都擁有一個屬於自己的 group id
classSolution { public: vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems){ // 對 group 進行前處理 : 賦予 groupId == -1 的 item 一個屬於自己的 new group id int newGroupId = m; for (int i = 0; i < n; ++i) { if (group[i] == -1) { group[i] = newGroupId++; } groupItems[group[i]].emplace(i); // 紀錄每個 group 所擁有的 item }
// 建立同一個 group 內的 graph for (int i = 0; i < n; ++i) { // j -> i (j 指向 i) for (int& j : beforeItems[i]) { // 不同 group 跳過 if (group[i] != group[j]) { continue; }
// 對同一 group 內的 item 進行 sorting unordered_map<int, vector<int>> groupItemOrder; for (constauto& [groupId, items] : groupItems) { groupItemOrder[groupId] = topologySort(items);
// group 內的 item 順序無解 if (groupItemOrder[groupId].size() != items.size()) { return {}; } }
// 建立不同 group 之間的 graph adj.clear(); inDegree.clear(); for (int i = 0; i < n; ++i) { // group[j] -> group[i] (group[j] 指向 group[i]) for (constauto& j : beforeItems[i]) { // 同一 group 跳過 if (group[i] == group[j]) { continue; }
// group 之間有可能會有重複 // e.g. 同一 group 內的 node 同時指向另外一個 group 的 node if (adj[group[j]].find(group[i]) == adj[group[j]].end()) { adj[group[j]].emplace(group[i]); ++inDegree[group[i]]; } } }
// 得到所有 group unordered_set<int> groups; for (int i = 0; i < n; ++i) { groups.emplace(group[i]); }
// 對不同 group 進行排序 vector<int> groupOrder = topologySort(groups); vector<int> res; for (constauto& groupId : groupOrder) { for (constauto& item : groupItemOrder[groupId]) { res.emplace_back(item); } }
return res; }
private: unordered_map<int, int> inDegree; unordered_map<int, unordered_set<int>> adj; // adjacency list unordered_map<int, unordered_set<int>> groupItems; // 紀錄每個 group 所有的 item
vector<int> topologySort(unordered_set<int>& nodes){ queue<int> q; for (constauto& node : nodes) { if (inDegree[node] == 0) { q.emplace(node); } }
vector<int> res; while (!q.empty()) { constauto cur = q.front(); q.pop(); res.emplace_back(cur);
for (constauto& v : adj[cur]) { if (--inDegree[v] == 0) { q.emplace(v); } } }