leetcode Parallel Courses III

在这里插入图片描述在这里插入图片描述

这是一道十分简单的类似于关键路径的题目。但是总超时。
发现还是针对于拓扑排序的代码为什么要那么做理解的不够深入
下面给出超时的代码:

class Solution {
    public int minimumTime(int n, int[][] relations, int[] time) {
        Map<Integer,List<Integer>> adjmap = new HashMap<>();
        int[] indegree = new int[n + 1];
        for(int i = 1;i<=n;i++)
            adjmap.put(i,new ArrayList<>());
        for(int[] a: relations)  //构造邻接图
        {
            List<Integer> temp  = adjmap.getOrDefault(a[0], new ArrayList<>());
            temp.add(a[1]);
            adjmap.put(a[0],temp);
            indegree[a[1]]++;  //入度
        }
        int[] earliest_start_time = new int[n + 1];
        int ans = 0;
        while(!adjmap.keySet().isEmpty())
        {
            Iterator<Integer> a = adjmap.keySet().iterator();
            while(a.hasNext())
            {
                int i = a.next();
                if(indegree[i] == 0)  //入读为0的结点删除
                {   
                    for(int j:adjmap.get(i))
                    {
                        earliest_start_time[j] = Math.max(earliest_start_time[j],earliest_start_time[i] + time[i - 1]);
                        indegree[j]--;
                    }
                    ans = Math.max(earliest_start_time[i]+time[i - 1],ans);
                    a.remove();
                }
            }
        }
        return ans;
    }

    public static void main(String[] args)
    {
        new Solution().minimumTime(3,new int[][]{{1,3},{2,3}},new int[]{3,2,5});
    }
}

超时的原因分析

  • 在循环中每次遍历所有的结点集合,这是不必要的
  • 只需要遍历入度为0的结点集合
  • 当从每个入度为0的结点考察后续结点时,新出现的入度为0的结点随即就可以得到,也就是if(indegree[i] == 0)的这些结点
    • 而完全不必重新遍历整个adjmap的Keyset

AC代码-队列实现的拓扑排序(标准的模板)

class Solution {
    public int minimumTime(int n, int[][] relations, int[] time) {
        Map<Integer,List<Integer>> adjmap = new HashMap<>();
        int[] indegree = new int[n + 1];
        for(int i = 1;i<=n;i++)
            adjmap.put(i,new ArrayList<>());
        for(int[] a: relations)  //构造邻接图
        {
            List<Integer> temp  = adjmap.getOrDefault(a[0], new ArrayList<>());
            temp.add(a[1]);
            adjmap.put(a[0],temp);
            indegree[a[1]]++;  //入度
        }
        int[] earliest_start_time = new int[n + 1];
        int ans = 0;
        Queue<Integer> q = new LinkedList<>();
        for(int i = 1;i<=indegree.length - 1;i++)
        {
            if(indegree[i] == 0)
            {
                ans = Math.max(ans,time[i - 1]);
                indegree[i] = -1;
                q.add(i);
            }
        }
        //拓扑排序
        while(!q.isEmpty())
        {
            //首元素出队
            int i = q.poll();
            for(int j:adjmap.get(i))
            {
                   indegree[j]--;
                   earliest_start_time[j]=Math.max(earliest_start_time[j],earliest_start_time[i] + time[i - 1]);
                   if(indegree[j] == 0)
                   {
                       indegree[j] = -1;
                       ans = Math.max(ans,earliest_start_time[j] + time[j - 1]);
                       q.add(j);
                   }
            }
        }
        return ans;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值