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