2021.9.8 华为笔试题第三题
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021.9.8 华为笔试题第三题相关的知识,希望对你有一定的参考价值。
复盘一下华为第三道笔试题,当时没时间了,马上就写完了,感觉每次在牛客做题都得调半天才能过
华为笔试最后一题基本都是出这种,当前任务依赖其他任务,拓扑排序这种题,或者是什么工序
题目描述
自己凭印象简单描述一下:
主要意思就是有一堆任务,然后任务之间有依赖关系,当前任务只有当前置任务完成以后,才能开始执行;每个任务有一个完成时间;
求出给定的一个目标任务最短的完成时间
思路
我的做法还是拓扑排序,先在一个哈希表中,键是任务编号,值是一个Set集合,里面存放的是这个任务所依赖的任务,也就是前置任务(可能需要存储二元组,加一个维度时间),也就是入度集合
可以将一个任务是哪些任务的前置任务,放到一个map里,方便后面查找,出度集合
因为输入都是字符串,module1,module2什么的,所以当时我是直接将里面的数字给分割出来然后用整数存储的,当时也意思到如果后面不是数字该怎么办,但是没时间了,就没考虑那么多
应该直接存储字符串就行了
处理好输入以后,然后定义一个结点Node类,里面两个属性,当前任务名称和时间
首先,先将没有前置任务的任务+时间,也就是Node,放到优先队列里,优先队列的排列顺序是按时间从小到大排序
每次弹出队首的任务top,说明这个任务在top.time时间完成了,然后找到这个任务top为前置任务的其他所有任务,将这个任务从他们的前置任务中删去,这里是复杂度的需要考量的地方,因为找当前任务为前置任务的其他任务,是O1的复杂度,遍历这些任务,删去当前任务,需要On(n为list中任务数目)的复杂度,我觉得这是最快的办法了
遍历list中任务删除的同时,将前置任务为空的任务,放入队列中,时间变成top.time加上当前任务的时间
直到弹出的任务是target,就说明target完成了,输出这个时间
想想对不对,应该没问题,因为在target开始的时候,必须是它前置任务都完成的时候,而前置任务同理,也是需要指定任务完成,而在每个任务入度为0的时候,就已经加入队列中了,所以其实任务的最早开始时间是固定的,所以最早完成时间也是固定的
重新写一下代码(输入输出就按印象中来了):
简单测试了一下,应该没问题
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String target = sc.nextLine(); //目标任务
Map<String, Set<String>> rel = new HashMap<>(); //当前任务,当前任务的前置任务集合set,入度
Map<String, List<String>> pre = new HashMap<>(); //前置任务,包含前置任务的任务集合list,出度
Map<String, Integer> map = new HashMap<>(); //任务-时间
List<String> nopre = new ArrayList<>(); //最开始没有前置任务的任务
//int idx = 0;
//while(idx++ < 4){ //测试
while(sc.hasNextLine()){ //每一行表示当前任务,完成时间,前置任务(多个)
String s = sc.nextLine();
String[] ss = s.split(" ");
String work = ss[0]; //当前任务
int time = Integer.parseInt(ss[1]); //完成时间
map.put(work, time);
Set<String> set = new HashSet<>();
for(int i = 2; i < ss.length; i++){
set.add(ss[i]);
//取出前置任务的集合
List<String> list = pre.getOrDefault(ss[i], new ArrayList<>());
list.add(work);
pre.put(ss[i], list);
}
//如果没有前置任务,放在nopre中
if(set.isEmpty()){
nopre.add(work);
}else{
rel.put(work, set);
}
}
PriorityQueue<Node> pq = new PriorityQueue<>((a,b) -> (a.time - b.time));
for(String s : nopre){
pq.offer(new Node(s, map.get(s)));
}
while(!pq.isEmpty()){
Node top = pq.poll();
String work = top.work;
int time = top.time;
//如果是目标工作
if(work.equals(target)){
System.out.println(time);
return;
}
//取出被当前工作所依赖的工作
List<String> list = pre.getOrDefault(work, new ArrayList<>());
//如果没有,跳过这个工作
if(list.isEmpty()){
continue;
}
for(String s : list){
//删除这个工作
Set<String> set = rel.get(s);
set.remove(work);
//如果set为空,加入队列,并且删除这个工作
if(set.isEmpty()){
pq.offer(new Node(s, time + map.get(s)));
rel.remove(s);
}else {
//如果不为空,还在rel里
rel.put(s, set);
}
}
}
//如果完不成这个任务就是-1
System.out.println(-1);
}
}
class Node{
String work;
int time;
public Node(String work, int time){
this.work = work;
this.time = time;
}
}
以上是关于2021.9.8 华为笔试题第三题的主要内容,如果未能解决你的问题,请参考以下文章