有趣的题 1203. 项目管理

公司共有 n 个项目和 m 个小组,每个项目要不没有归属,要不就由其中的一个小组负责。

我们用 group[i] 代表第 i 个项目所属的小组,如果这个项目目前无人接手,那么 group[i] 就等于
-1。(项目和小组都是从零开始编号的)

请你帮忙按要求安排这些项目的进度,并返回排序后的项目列表:

同一小组的项目,排序后在列表中彼此相邻。 项目之间存在一定的依赖关系,我们用一个列表 beforeItems 来表示,其中
beforeItems[i] 表示在进行第 i 个项目前(位于第 i 个项目左侧)应该完成的所有项目。 结果要求:

如果存在多个解决方案,只需要返回其中任意一个即可。

如果没有合适的解决方案,就请返回一个 空列表。

示例 1:

输入:n = 8, m = 2,
group = [-1,-1,1,0,0,1,0,-1],
beforeItems = [[],[6],[5],[6],[3,6],[],[],[]]

输出:[6,3,4,1,5,2,0,7]

示例 2:

输入:n = 8, m = 2,
group = [-1,-1,1,0,0,1,0,-1],
beforeItems = [[],[6],[5],[6],[3],[],[4],[]]

输出:[]

解释:与示例 1 大致相同,但是在排序后的列表中,4 必须放在 6 的前面。

提示:

1 <= m <= n <= 3*10^4

group.length == beforeItems.length == n

-1 <= group[i] <= m-1

0 <= beforeItems[i].length <= n-1

0 <= beforeItems[i][j] <= n-1

i != beforeItems[i][j]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-items-by-groups-respecting-dependencies
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

两遍拓扑排序 先对组内进行排序 然后对所有分组进行排序
对于没有组的其实可以当成单独一个在一组,在最开始给所有没有组的分配上组就好
拓扑排序就dfs就好

class Solution {

    List<LinkedList<Integer>> groupAns;
    List<HashSet<Integer>> groupEdges;
    int[] group;
    List<List<Integer>> beforeItems;
    int[] color;
    List<Integer> groupSort;
    int m;

    boolean dfs(int i) {
        if(color[i] == 2) {
            //黑色直接返回就好
            return false;
        }
        if(color[i] == 1) {
            return true;//说明存在环
        }
        color[i] = 1;
        for(int to : beforeItems.get(i)) {
            if(group[i] != group[to]) {
                //记录到组的边里 暂时不管
                groupEdges.get(group[i]).add(group[to]);
            } else {
                if(dfs(to)) {
                    return true;
                }
            }
        }
        groupAns.get(group[i]).add(i);
        color[i] = 2;
        return false;
    }

    boolean dfsGroup(int i) {
        
        if(color[i] == 2) {
            //黑色直接返回就好
            return false;
        }
        if(color[i] == 1) {
            return true;//说明存在环
        }
        color[i] = 1;
        
        for(int to : groupEdges.get(i)) {
            if(dfsGroup(to)) {
                return true;
            }
        }
        groupSort.add(i);
        color[i] = 2;
        return false;
    }

    public int[] sortItems(int n, int m, int[] group, List<List<Integer>> beforeItems) {
        //每个组内部排序
        this.group = group;
        this.beforeItems = beforeItems;
        groupAns = new ArrayList<>();//每个组内的拓扑排序
        groupEdges = new ArrayList<>();//每个组的出边
        groupSort = new ArrayList<>();//组的排序
        color = new int[n];
        //没组的编上组
        for(int i = 0; i < n; ++i) {
            if(group[i] == -1) {
                group[i] = m;
                ++m;
            }
        }

        for(int i = 0; i < m; ++i) {
            groupAns.add(new LinkedList<>());
            groupEdges.add(new HashSet<>());
        }

        //第一遍遍历 把组间的边记录上 组内进行dfs
        for(int i = 0; i < n; ++i) {
            if(dfs(i) == true) {
                //存在组内环 直接返回
                return new int[0];
            }
        }

        color = new int[m];
        //第二遍遍历 给组排序
        for(int i = 0; i < m; ++i) {
            if(dfsGroup(i) == true) {
                //存在环 直接返回
                return new int[0];
            }
        }

		//根据所有组的结果构造答案
        int[] ret = new int[n];
        int index = 0;
        for(int i : groupSort) {
            for(int node : groupAns.get(i)) {
                ret[index] = node;
                ++index;
            }
        }

        return ret;
    }
}

实现起来比想起来轻松多了
但是做出来是真的快乐

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值