Skip to content

华为笔试题2023-04-26

笔试时间:2023年4月26日 19:00-21:00

注:因为本次第二题很容易超时(只有使用C++有可能过),导致很多人都没拿到150分,所以华为在2023-05-06举行了第二次笔试。

1、批量初始化次数(100分)

某部门在开发一个代码分析工具,需要分析代确模块之间的依赖关系,用来确定模块的初始化顺序、是否有循环依赖等问题。“批量初始化“是指一次可以初始化一个或多个模块。例如模块1依赖模块2,模块3也依赖模块2,但模块1和3没有依赖关系。则必须先“批量初始化”模块2,再“批量初始化”模块1和3,现给定一组模块间的依赖关系,请计算需要“批量初始化”的次数。

解答要求

时间限制:C/C++ 1000ms,其他语言:2000ms 内存限制:C/C++ 256MB,其他语言:512MB

输入

(1)第1行只有一个数字,表示模块总数N。 (2)随后的N行依次表示模块1到N的依赖数据。 每行的第1个数据表示依赖的模块数量(不会超过N),之后的数字表示当前模块依赖的模块ID序列,该序列不会重复出现相同的数字,模块ID的取值一定在[1, N]之内。 (3)模块总数N取值范围为1<=N<=1000。 (4)每一行里面的数字按一个空格分隔。

输出

输出“批量初始化次数”,若有循环依赖无法完成初始化,则输出-1。

测试样例

输入 5 3 2 3 4 1 5 1 5 1 5 0

输出 3

输入 3 1 2 1 3 1 1

输出 -1

代码

100%通过

java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] inDegree = new int[n+1]; // 入度数组
        List<List<Integer>> graph = new ArrayList<>(); // 图
        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<>());
        }
        for (int i = 1; i <= n; i++) {
            int num = scanner.nextInt();
            for (int j = 0; j < num; j++) {
                int id = scanner.nextInt();
                graph.get(id).add(i); // 构建有向图,id指向i
                inDegree[i]++; // i的入度加1
            }
        }
        int count = 0; // 批量初始化次数
        Queue<Integer> queue = new LinkedList<>(); // 存放入度为0的结点
        for (int i = 1; i <= n; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i); // 将入度为0的结点加入队列
            }
        }
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int cur = queue.poll();
                for (int next : graph.get(cur)) {
                    inDegree[next]--; // 将cur指向的结点入度减1
                    if (inDegree[next] == 0) {
                        queue.offer(next); // 将入度变为0的结点加入队列
                    }
                }
            }
            count++; // 批量初始化次数加1
        }
        for (int i = 1; i <= n; i++) { // 检查是否存在循环依赖
            if (inDegree[i] != 0) {
                System.out.println(-1);
                return;
            }
        }
        System.out.println(count);
    }
}

2、分配资源ID(200分)

给定一个管理ID的资源池,可以从资源池中分配资源ID和释放资源ID,分配方式有动态分配和指定分配,动态分配是从资源池的开始分配一个资源ID,指定分配是指定一个资源ID进行分配,无论哪种分配方式释放资源ID时都需要放到资源池的尾部。执行一系列操作后,请问资源池的第一个空闲资源ID应该是多少?

注意: 资源池的初始顺序是从小到大。 资源池中空闲资源ID不足时,动态分配失败,对资源池不进行任何操作。 指定分配资源ID已经被占用或者不在资源池范围内时,对资源池不进行任何操作。 释放资源ID不在资源池范围内时或者已经是空闲资源ID时,对资源池不进行任何操作。 保证每个用例最后都有空闲资源ID。

解答要求

时间限制:C/C++ 100ms,其他语言:200ms 内存限制:C/C++ 32MB,其他语言:64MB

输入

第一行是资源池的范围; 第二行是操作个数。 第三行开始,第一个数字代表操作类型,1表示动态分配,2表示指定分配,3表示释放; 如果第一个数字是1,第二个表示分配的个数; 如果第一个数字是2,第二个表示分配的资源ID; 如果第一个数字是3,第二个表示释放的资源ID。

输出

资源池的第一个空闲资源ID。

测试样例

输入 1 3 2 1 1 3 1 输出 2

输入 1 3 3 2 2 3 2 1 1 输出 3

代码

测试用例通过,提交通过4%,提示超时。

java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int rangeFrom = scanner.nextInt(), rangeTo = scanner.nextInt();
        LinkedList<Integer> resources = new LinkedList<>();
        for (int i = rangeFrom; i <= rangeTo; i++) {
            resources.addLast(i);
        }
        int n = scanner.nextInt();
        int resID, count;
        for (int i = 0; i < n; i++) {
            switch (scanner.nextInt()) {
                case 1:
                    count = scanner.nextInt();
                    if (resources.size() < count) {
                        continue;
                    }
                    resources.subList(0, count).clear();
                    break;
                case 2:
                    resID = scanner.nextInt();
                    resources.remove(Integer.valueOf(resID));
                    break;
                case 3:
                    resID = scanner.nextInt();
                    if (resID >= rangeFrom && resID <= rangeTo && !resources.contains(resID))
                        resources.addLast(resID);
                    break;
            }
        }
        System.out.println(resources.getFirst());
    }
}