【学习笔记】leetcode1203

 

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> 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 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 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> 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 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 sort(Integer[] ids, Item[] items, int[] degrees) {
        List ret = new LinkedList<>();
        Deque 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 adjecent;
    public Item(int id) {
        this.id = id;
        adjecent = new HashSet<>();
    }
}

class Group extends Item{
    Set items;
    public Group(int id) {
        super(id);
        items = new HashSet<>();
    }
}

 

你可能感兴趣的:(JAVA)