【学习笔记】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<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<>();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值