LeetCode刷题记168
1203. 项目管理
class Solution {
public int[] sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
int k = m;
for (int i = 0; i < n; i ++) {
if(group[i] == -1) group[i] = k ++; // 给没有分类的组赋予一个新的组别号
}
List<Integer>[] itemsOfGroup = new ArrayList[k]; // 记录每个组的任务
for (int i = 0; i < k; i ++) {
itemsOfGroup[i] = new ArrayList<Integer>();
}
for (int i = 0; i < n; i ++) {
itemsOfGroup[group[i]].add(i);
}
Set<Integer>[] afterGroups = new HashSet[k]; // 记录每个组的后置组
Set<Integer>[] afterItems = new HashSet[n]; // 记录每个任务的组内后置任务
for (int i = 0; i < k; i ++) {
afterGroups[i] = new HashSet<Integer>();
}
for (int i = 0; i < n; i ++) {
afterItems[i] = new HashSet<Integer>();
}
for (int i = 0; i < n; i ++) {
int curGroupId = group[i]; // 当前组的组别名
for (Integer id : beforeItems.get(i)) {
int befGroupId = group[id]; // 前置组别名
if (befGroupId == curGroupId) { // 同组内的前置
afterItems[id].add(i);
} else { // 添加到后置组中
afterGroups[befGroupId].add(curGroupId);
}
}
}
int[] beforeGroupsNum = new int[k]; // 前置组的数量
for (int i = 0; i < k; i ++) {
for (Integer id : afterGroups[i]) {
beforeGroupsNum[id] ++;
}
}
int[] beforeItemsNum = new int[n]; // 同组内前置的任务数量
for (int i = 0; i < n; i ++) {
for (Integer id : afterItems[i]) {
beforeItemsNum[id] ++;
}
}
int[] ans = new int[n];
int ansId = 0;
// 外层对组间进行拓扑排序
Queue<Integer> queueGroup = new LinkedList<Integer>();
for (int i = 0; i < k; i ++) {
if (beforeGroupsNum[i] == 0) {
queueGroup.add(i);
}
}
while (!queueGroup.isEmpty()) {
int curGroupId = queueGroup.poll();
// 对组内进行拓扑排序
Queue<Integer> queueItem = new LinkedList<Integer>();
for (Integer id : itemsOfGroup[curGroupId]) {
if (beforeItemsNum[id] == 0) {
queueItem.add(id);
}
}
int itemNum = 0;
while (!queueItem.isEmpty()) {
int curItemId = queueItem.poll();
itemNum ++;
ans[ansId ++] = curItemId;
for (Integer id : afterItems[curItemId]) {
beforeItemsNum[id] --;
if (beforeItemsNum[id] == 0) {
queueItem.add(id);
}
}
}
if (itemNum != itemsOfGroup[curGroupId].size()) {
return new int[]{}; // 组内拓扑排序不满足
}
for (Integer id : afterGroups[curGroupId]) {
beforeGroupsNum[id] --;
if (beforeGroupsNum[id] == 0) {
queueGroup.add(id);
}
}
}
if (ansId != n) return new int[]{}; // 组间拓扑排序不满足
return ans;
}
}
两层拓扑,这个题目我竟然一发就过了,好嗨心~