[LeetCode] Sort Items by Groups Respecting Dependencies

1203. Sort Items by Groups Respecting Dependencies

There are n items each belonging to zero or one of m groups where group[i] is the group that the i-th item belongs to and it’s equal to -1 if the i-th item belongs to no group. The items and the groups are zero indexed. A group can have no item belonging to it.

Return a sorted list of the items such that:

  • The items that belong to the same group are next to each other in the sorted list.
  • There are some relations between these items where beforeItems[i] is a list containing all the items that should come before the i-th item in the sorted array (to the left of the i-th item).

Return any solution if there is more than one solution and return an empty list if there is no solution.

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
class Solution {
vector<unordered_set<int>> groupOrder;
vector<int> groupOrderCounter;
vector<vector<int>> groupping;

vector<int> unGroupCounter;

vector<vector<int>> beforeItemsOrder;
vector<int> beforeItemsCounter;

unordered_set<int> unGroup;
unordered_set<int> unUsed;
unordered_set<int> unUsedGroup;

vector<int> res;

void initGroupMembers(vector<int>& group) {
for(int i = 0; i < group.size(); i++) {
unUsed.insert(i);
if(group[i] == -1) {
unGroup.insert(i);
} else {
groupping[group[i]].push_back(i);
}
}
}

void initGroupOrder(vector<int>& group, vector<vector<int>>& beforeItems, int n) {
for(int i = 0; i < n; i++) {
int selfGroup = group[i];
for(auto before : beforeItems[i]) {
int beforeGroup = group[before];
if(selfGroup != -1) {
if(beforeGroup != -1) {
if(beforeGroup != selfGroup and groupOrder[beforeGroup].insert(selfGroup).second) {
groupOrderCounter[selfGroup]++;
}
} else {
unGroupCounter[selfGroup]++;
}
}
beforeItemsOrder[before].push_back(i);
beforeItemsCounter[i]++;
}
}
}

void pushUnGroupItems(vector<int>& group) {
for(auto un : unGroup) { //select -1 group
if(beforeItemsCounter[un] == 0) {
res.push_back(un);
for(auto after : beforeItemsOrder[un]) {
beforeItemsCounter[after]--;
if(group[after] != -1) {
unGroupCounter[group[after]]--;
}
}
}
}
}

void sortingGroupItems(vector<int>& group, int groupId) {
queue<int> q;
for(auto member : groupping[groupId]) {
if(beforeItemsCounter[member] == 0)
q.push(member);
}

while(!q.empty()) {
auto member = q.front(); q.pop();
res.push_back(member);
for(auto after : beforeItemsOrder[member]) {
if(--beforeItemsCounter[after] == 0 and group[after] == groupId) {
q.push(after);
}
}
}

for(auto after : groupOrder[groupId]) {
groupOrderCounter[after]--;
}
}

void eraseUsedGroupAndItems(vector<int>& group, int from) {
for(int i = from; i < res.size(); i++) {
unUsed.erase(res[i]);
if(group[res[i]] != -1) {
unUsedGroup.erase(group[res[i]]);
} else {
unGroup.erase(res[i]);
}
}
}
public:
vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems) {

groupping = vector<vector<int>>(m);

groupOrder = vector<unordered_set<int>>(m);
groupOrderCounter = vector<int>(m);
unGroupCounter = vector<int>(m);

beforeItemsOrder = vector<vector<int>>(n);
beforeItemsCounter = vector<int>(n);

for(int i = 0; i < m; i++) unUsedGroup.insert(i);

initGroupMembers(group);
initGroupOrder(group, beforeItems, n);


while(!unUsed.empty()) {
int beforeSize = res.size();

pushUnGroupItems(group);

for(auto gr : unUsedGroup) {
if(groupOrderCounter[gr] == 0 and unGroupCounter[gr] == 0) {
sortingGroupItems(group, gr);
}
}

if(beforeSize == res.size())
return {};

eraseUsedGroupAndItems(group, beforeSize);
}

return res;

}
};
Author: Song Hayoung
Link: https://songhayoung.github.io/2022/03/07/PS/LeetCode/sort-items-by-groups-respecting-dependencies/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.