[leetCode]1203. 项目管理

题目

https://leetcode-cn.com/problems/sort-items-by-groups-respecting-dependencies/

在这里插入图片描述

拓扑排序

每个项目之间存在执行的先后顺序,因此可以对项目拓扑排序得到一个列表。 项目与组是一对多的关系也可以对组进行一个拓扑排序的到组的先后顺序。由项目的拓扑排序可以得到组与项目的一对多的关系,将组的拓扑排序替换为项目的拓扑排序即可得到结果。

class Solution {
    public int[] sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
        // 第一步:给没有承接任何项目的小组上一个编号
        for (int i = 0; i < group.length; i++) {
            if (group[i] == -1) {
                group[i] = m++;
            }
        }
        // 第二步: 实例化组和项目的邻接表
        List<Integer>[] groupAdj = new ArrayList[m];
        List<Integer>[] itemAdj = new ArrayList[n];
        for (int i = 0; i < m; i++) groupAdj[i] = new ArrayList<>(); 
        for (int i = 0; i < n; i++) itemAdj[i] = new ArrayList<>();

        // 第三步: 建图并统计入读数组
        int[] groupsIndegree = new int[m];
        int[] itemsIndegree = new int[n];

        int len = group.length;
        for (int i = 0; i < len; i++) {
            int currentGroup = group[i];
            for (Integer item : beforeItems.get(i)) {
                int beforeGroup = group[item];
                if (beforeGroup != currentGroup) {
                    groupAdj[beforeGroup].add(currentGroup);
                    groupsIndegree[currentGroup]++;
                }
            }
        }

        for (int i = 0; i < len; i++) {
            for (Integer item : beforeItems.get(i)) {
                itemAdj[item].add(i);
                itemsIndegree[i]++;
            }
        }

        // 第四步: 得到组和项目的拓扑结果
        List<Integer> groupList = topologicalSort(groupAdj, groupsIndegree, m);
        if (groupList.size() == 0) {
            return new int[0];
        }

        List<Integer> itemList = topologicalSort(itemAdj, itemsIndegree, n);
        if (itemList.size() == 0) {
            return new int[0];
        }

        // 第五步: 根据项目的拓扑排序结果,简历组到项目的1对多关系
        Map<Integer, List<Integer>> groups2Items = new HashMap<>();
        for (Integer item : itemList) {
            groups2Items.computeIfAbsent(group[item], k -> new ArrayList<>()).add(item);
        } 

        // 第六步: 把组的拓扑排序结果替换成项目的拓扑排序结果
        List<Integer> res = new ArrayList<>();
        for (Integer groupId : groupList) {
            List<Integer> items = groups2Items.getOrDefault(groupId, new ArrayList<>());
            res.addAll(items);
        }
        return res.stream().mapToInt(Integer::valueOf).toArray();
    }

    private List<Integer> topologicalSort(List<Integer>[] adj, int[] indegree, int n) {
        List<Integer> res = new ArrayList<>();
        Queue<Integer> queue = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            if (indegree[i] == 0) {
                queue.offer(i);
            }
        }
        while (!queue.isEmpty()) {
            int front = queue.poll();
            res.add(front);
            for (int successor : adj[front]) {
                indegree[successor]--;
                if (indegree[successor] == 0) {
                    queue.offer(successor);
                }
            }
        }
        if (res.size() != n)
            return new ArrayList<>();
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值