public class Solution {
int groupNumx = 0;
int[] itemIndegree = null;
int[] groupIndegree = null;
Item[] items = null;
Group[] groups = null;
public int[] sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
if (n == 0 || group == null || group.length == 0 || beforeItems == null || beforeItems.size() == 0) {
return new int[0];
}
init(n, m, group, beforeItems);
Integer[] groupIdx = new Integer[groupNumx];
for (int i = 0; i < groupNumx; i++) {
groupIdx[i] = i;
}
List<Integer> groupG = sort(groupIdx, groups, groupIndegree);
if (groupG == null) {
return new int[0];
}
int[] ret = new int[n];
int idx = 0;
for (int g : groupG) {
List<Integer> itemG = sort(groups[g].items.toArray(new Integer[0]), items, itemIndegree);
if (itemG == null) {
return new int[0];
}
for (int item : itemG) {
ret[idx++] = item;
}
}
return ret;
}
private void init(int n, int m, int[] group, List<List<Integer>> beforeItems) {
groupNumx = 0;
int g = 0;
for (int i = 0; i < n; i++) {
if (group[i] == -1) {
group[i] = m + g++;
}
}
groupNumx = g + m;
groupIndegree = new int[groupNumx];
groups = new Group[groupNumx];
for (int i = 0; i < groupNumx; i++) {
groups[i] = new Group(i);
}
items = new Item[n];
itemIndegree = new int[n];
for (int i = 0; i < n; i++) {
items[i] = new Item(i);
groups[group[i]].items.add(i); // 每个项目组初始包含一个项目
}
for (int i = 0; i < beforeItems.size(); i++) {
// i 是item的id
// list是item i的前置节点
List<Integer> list = beforeItems.get(i);
// j 是前置节点
for (int j : list.toArray(new Integer[0])) {
if (group[i] == group[j]) { // 因为先按项目组排序,再按项目排序,所以只计算同一项目组的项目入度
itemIndegree[i]++;
items[j].adjecent.add(i);
groups[group[j]].items.add(i);
groups[group[j]].items.add(j);
} else { // 两个组之间存在依赖
groups[group[j]].adjecent.add(group[i]);
}
}
}
// 更新项目组节点的入度
for (int j = 0; j < groups.length; j++) {
// j 是前置项目组
// k 是子节点
for (int k : groups[j].adjecent.toArray(new Integer[0])) {
groupIndegree[k]++;
}
}
}
private List<Integer> sort(Integer[] ids, Item[] items, int[] degrees) {
List<Integer> ret = new LinkedList<>();
Deque<Integer> deque = new LinkedList<>();
for (int id : ids) {
if (degrees[id] == 0) {
deque.add(id);
}
}
while (!deque.isEmpty()) {
int id = deque.poll();
ret.add(id);
Integer[] adjecents = items[id].adjecent.toArray(new Integer[0]);
for (int adjecent : adjecents) {
if (--degrees[adjecent] == 0) {
deque.addFirst(adjecent); // 由于同一组的项目要相邻,所以采用深度遍历
}
}
}
if (ret.size() != ids.length) {
return null;
}
return ret;
}
}
class Item {
int id;
Set<Integer> adjecent;
public Item(int id) {
this.id = id;
adjecent = new HashSet<>();
}
}
class Group extends Item{
Set<Integer> items;
public Group(int id) {
super(id);
items = new HashSet<>();
}
}