乐于分享
好东西不私藏

华为非AI方向实习机考 | 6月24日最新笔试题与解析

华为非AI方向实习机考 | 6月24日最新笔试题与解析

写在前面

本次给大家带来2026年6月24日华为非AI方向笔试题的3道题,涉及到的岗位是:通软,嵌软,测试,普通算法(岗位名中不包含AI)以及数据科学,和报考部门无关,统一考本套卷子。

我整理的考试题单+攻略可访问文章底部左侧:阅读原文

第一题:将电影按结束时间从早到晚排序,每次优先选择当前能播放且结束最早的电影,用贪心保证后续可选空间最大。

第二题:这题思路就是用队列模拟大厅排队、用数组模拟窗口服务,每秒让窗口中的顾客各买  笼,没买够就回队尾,直到第  位顾客买完为止;

第三题:利用前序和中序遍历递归确定二叉树结构,同时维护根节点到当前节点的路径和,路径和小于等于  时剪掉整棵子树,否则记录路径和,最后排序并取最大的  个。

塔子哥的配套刷题网站:codefun2000.com

题号
题目
难度(对标leetcode)
核心做法
1
电影放映调度问题
中等
贪心算法
2
快来排队买包子
中等
模拟
3
K大小统计
困难
二叉树

第1题-电影放映调度问题

题目内容

某电影院有  块银幕,每天需要安排多部电影在不同时段进行放映。每部电影有固定的放映时长和要求的放映时间段,且每个被选中放映的电影确保在对应时段能够完整占用。由于每块银幕同一时间只能放映一部电影,需要合理规划,使得每天能够放映的电影数量最多。如果第一场电影结束时间与第二场电影的开始时间相同,能够连续放映。

给定  部电影的放映时间区间,请计算最多可以放映多少部电影。

输入描述

第一行:  (电影数量) , 

接下来  行: 每行两个整数  和  , 表示第  部电影的放映开始时间和结束时间,  (一天内的分钟数) (时间以分钟表示,  小时为  分钟; 如 )

输出描述

一个整数: 最多可以放映的电影数量

样例1

输入

3540 660540 600660 780

输出

2

说明

最多可以  部电影, 可以选择 - 和 -, 或者 - 和 -

样例2

输入

50 1000100 900200 800300 700400 600

输出

1

说明

因为各电影的播放时间均有重叠, 所以最多可以有一部电影播放

题解

解题思路

本题是典型的区间调度问题,可以使用贪心算法解决。

每部电影看作一个区间 。因为同一块银幕同一时间只能播放一部电影,所以要选择尽可能多的不重叠区间。

贪心策略:

先将所有电影按照结束时间  从小到大排序。

然后依次遍历电影:

若当前电影的开始时间  大于等于上一部已选择电影的结束时间 ,则可以选择这部电影。

因为结束越早,留给后面电影的时间越多,所以该贪心策略是正确的。

注意:题目说明若上一部电影结束时间和下一部电影开始时间相同,可以连续播放,所以判断条件是 

复杂度分析

排序需要  的时间。

遍历所有电影需要  的时间。

因此总时间复杂度为 

需要存储  个电影区间,空间复杂度为 

代码实现

python代码(C++和JAVA代码见在线OJ网址)

import sys# 计算最多可以播放的电影数量defmax_movies(intervals):# 按结束时间从小到大排序    intervals.sort(key=lambda x: x[1])    ans = 0    last_end = -1# 贪心选择结束最早且不冲突的电影for start, end in intervals:if start >= last_end:            ans += 1            last_end = endreturn ansdefmain():    data = sys.stdin.read().strip().split()    n = int(data[0])    intervals = []    idx = 1# 读取每部电影的开始和结束时间for _ in range(n):        start = int(data[idx])        end = int(data[idx + 1])        intervals.append((start, end))        idx += 2    print(max_movies(intervals))if __name__ == "__main__":    main()

第2题-快来排队买包子

题目内容

富春包子被誉为扬州包子的“天花板”, 前来购买的顾客络绎不绝。

大厅中有  位顾客等待叫号 (按顾客到大厅取号的顺序, 第一个取号的是第  位, 以此类推.. (最多  位顾客, 且不会有新顾客到来) ) ;

包子铺有  个窗口, 每个窗口每次服务一位顾客, 服务时长  秒; 当有多个窗口空闲时, 会从大厅队伍中同时叫号, 不会让窗口空闲 (比如大厅有  个人, 空着  个窗口, 会从大厅中叫前  个人分配到空闲窗口) , 且系统会优先分配编号最小的窗口;

每位顾客一次只能买一笼包子, 如果他已买到想要的包子笼数, 会直接离开大厅; 如果还想买更多, 需回到大厅重新取号, 取号后排到等待叫号的顾客末尾。

给你一个整数数组 , 数组长度为  是第  位顾客想要购买包子的笼数。请计算出在大厅中排在第  位的顾客购买完所有包子时, 其花费的总时间 (秒)。

输入描述

第一行: 购买包子列表 , 列表中每个元素表示顾客计划购买的包子笼数 (, 顾客数量  的约束条件为 ) , 以空格隔开

第二行: 在大厅中排在第  位的顾客 (下标从  开始, )

第三行: 窗口数量  ()

输出描述

大厅中排在第  位 (下标从  开始) 的顾客完成其想要购买包子所需的总时间 (秒)

样例1

输入

2 1 222

输出

3

说明

为方便理解,  () 表示首位客户需要买包子  笼, 以此类推。大厅中队伍初始为 ,

开始分配:

窗口  分配给  (需求:  笼)

窗口  分配给  (需求:  笼)

大厅: 

窗口: 窗口 :, 窗口 :

s 后:

 买完一笼, 剩余  笼, 回到大厅

 完成购买, 离开

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

大厅: 

窗口: 窗口 :, 窗口 :

s 后:

 买完一笼, 剩余  笼, 回到大厅

 完成购买, 离开

窗口  分配给(需求: 笼)

大厅: 

窗口: 窗口 :, 窗口 : 空

s 后:

目标顾客  完成购买!

总耗时: 秒

样例2

输入

5 3 3 1 423

输出

4

说明

为方便理解,  () 表示首位客户需要买包子  笼, 以此类推。大厅中队伍初始为 

开始分配:

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

大厅: 

窗口: 窗口 :, 窗口 :, 窗口 :

s 后:

 买完一笼, 剩余  笼, 回到大厅

 买完一笼, 剩余  笼, 回到大厅

 买完一笼, 剩余  笼, 回到大厅

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

大厅: 

窗口: 窗口 :, 窗口 :, 窗口 :

s 后:

 完成购买, 离开

 买完一笼, 剩余  笼, 回到大厅

 买完一笼, 剩余  笼, 回到大厅

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

大厅: 

窗口: 窗口 :, 窗口 :, 窗口 :

s 后:

 买完一笼, 剩余  笼, 回到大厅

 买完一笼, 剩余  笼, 回到大厅

 买完一笼, 剩余  笼, 回到大厅

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

窗口  分配给 (需求: 笼)

大厅: 

窗口: 窗口 :, 窗口 :, 窗口 :

s 后:

 买完一笼, 剩余  笼, 回到大厅

 完成购买, 离开

目标顾客  完成购买!

总耗时: 秒

题解

解题思路

本题可以直接使用队列模拟。

把大厅中的等待顾客按顺序放入队列,窗口用数组记录当前正在服务的顾客编号。

核心规则如下:

  1. 开始时,将队列前面的顾客依次分配给空窗口,优先分配编号小的窗口。
  2. 每经过  秒,每个非空窗口中的顾客买到  笼包子。
  3. 如果顾客还没买够,就回到队尾。
  4. 如果顾客已经买够,就直接离开。
  5. 同一秒内,先处理所有窗口服务完成的顾客,再重新给空窗口分配大厅队首顾客。
  6. 当编号为  的顾客买完最后一笼包子时,当前时间就是答案。

由于最多只有  位顾客,每位最多买  笼,直接模拟总服务次数即可,算法简单且不会超时。

复杂度分析

设顾客总共需要购买的包子笼数为 

每秒最多处理  个窗口,但每次处理都会让某位顾客的需求减少 ,因此总处理次数为 

时间复杂度为 

队列和窗口数组最多存储  个元素。

空间复杂度为 

代码实现

python代码(C++和JAVA代码见在线OJ网址)

from collections import dequedefsolve(baskets, k, m):    n = len(baskets)    rest = baskets[:]              # 记录每位顾客还需要买几笼    q = deque(range(n))            # 大厅等待队列    windows = [-1] * m             # 每个窗口当前服务的顾客编号,-1 表示空# 初始分配顾客到窗口for i in range(m):if q:            windows[i] = q.popleft()    time = 0whileTrue:        time += 1# 当前这一秒内,所有非空窗口各服务一位顾客一次for i in range(m):if windows[i] != -1:                cid = windows[i]                rest[cid] -= 1# 处理服务结束后的顾客for i in range(m):if windows[i] != -1:                cid = windows[i]# 目标顾客买完,直接返回答案if cid == k and rest[cid] == 0:return time# 没买够的顾客回到队尾if rest[cid] > 0:                    q.append(cid)# 当前窗口变为空                windows[i] = -1# 给空窗口重新分配顾客,优先编号小的窗口for i in range(m):if windows[i] == -1and q:                windows[i] = q.popleft()if __name__ == "__main__":    baskets = list(map(int, input().split()))    k = int(input())    m = int(input())    print(solve(baskets, k, m))

第3题-容器镜像Top-K大小统计

题目内容

在容器镜像管理系统中, 容器镜像通常采用堆叠方式管理和挂载, 为了减少镜像管理系统中重复的镜像层数量, 假定容器镜像层采用二叉树管理。镜像层二叉树节点描述镜像层大小, 节点的镜像完整大小为镜像层大小及其所有父节点镜像层大小之和。由于业务需要, 现在需要对系统中所有的客户镜像大小统计分析, 从小到大输出最大的  个镜像大小; 输入为容器镜像二叉树前序遍历数组和中序遍历数组, 输出为最大的  个镜像大小, 并按从小到大排序输出。

说明: 当镜像完整大小小于等于  时, 则表示该镜像节点异常, 异常镜像节点需要剪枝; 例如: 节点  有子节点  和子节点 , 如果节点  完整镜像大小为 , 则节点  需要剪枝, 即节点 、节点 、节点 均需要从镜像二叉树中删除。

输入描述

第一行: 容器镜像树前序遍历结果。

第二行: 容器镜像树中序遍历结果。

第三行: 需要统计的最大容器镜像个数, 取值范围为 [,]。

说明:

  1. 容器镜像树前序遍历、中序遍历结果中的数字表示当前镜像层大小, 取值范围为 [,]。

  2. 镜像层大小为负数时表示该层基于父镜像裁剪文件, 镜像层为正数时表示该层基于父镜像新增文件,  则表示镜像层未做任何更改或者裁剪文件大小与新增文件大小相等;

  3. 节点规模数量 

  4. 为了能够通过前序遍历和中序遍历还原唯一的镜像二叉树, 输入的各节点镜像层大小都不相同。

输出描述

从小到大输出最大的镜像大小。

说明:

  1. 如果二叉树节点总数小于需要统计  数量, 则从小到大输出所有镜像大小。

  2. 如果二叉树剪枝后为空, 则输出 

样例1

输入

8 2 -3 9 52 8 9 -3 53

输出

10 10 14

说明

根据  前序遍历,  中序遍历, 得到左图所示二叉树, 每个节点数字为对应镜像层大小; 每个节点镜像大小为自身节点镜像层大小加上所有父节点镜像层大小, 如右图所示为计算之后的各节点镜像实际大小。 一共有  个镜像, 镜像大小分别是 , 所以  从小到大排序为

样例2

输入

1 2 3 -5 5 62 1 3 5 -5 61

输出

4

说明

左图为输入的二叉树, 由于  节点计算出镜像完整大小为 , 小于等于 , 因此属于非法节点, 需要剪枝处理, 剪枝后得到最右边的二叉树, 一共三个镜像, 镜像大小为 

题解

解题思路

根据前序遍历和中序遍历还原二叉树。由于节点值互不相同,可以用哈希表记录每个节点值在中序遍历中的位置。

还原过程中不一定要真的建树,可以递归处理前序和中序对应区间:

:前序区间第一个值就是当前根节点。

:通过中序位置划分左子树和右子树。

:递归时维护从根到当前节点的路径和,也就是当前节点的镜像完整大小。

:如果当前路径和小于等于 ,说明当前节点异常,整棵子树剪枝,后续子节点不再统计。

:否则记录当前路径和,并继续递归左右子树。

:最后将所有合法镜像大小从小到大排序,输出最大的  个;如果没有合法节点,输出 

用到的核心算法是:二叉树遍历还原、递归 、剪枝、排序。

复杂度分析

设节点数量为 

时间复杂度为 。 其中递归遍历每个节点最多一次,复杂度为 ;最后对合法镜像大小排序,复杂度为 

空间复杂度为 。 哈希表、递归栈和结果数组都需要额外空间。

代码实现

python代码(C++和JAVA代码见在线OJ网址)

import sysdefget_top_images(preorder, inorder, k):# 建立中序遍历中,节点值到下标的映射    pos = {}for i, v in enumerate(inorder):        pos[v] = i    ans = []defdfs(pre_l, pre_r, in_l, in_r, parent_sum):# 区间为空,直接返回if pre_l > pre_r:return        root = preorder[pre_l]        cur_sum = parent_sum + root# 当前节点异常,整棵子树剪枝if cur_sum <= 0:return        ans.append(cur_sum)        mid = pos[root]        left_size = mid - in_l# 递归处理左子树        dfs(pre_l + 1, pre_l + left_size, in_l, mid - 1, cur_sum)# 递归处理右子树        dfs(pre_l + left_size + 1, pre_r, mid + 1, in_r, cur_sum)    n = len(preorder)    dfs(0, n - 10, n - 10)ifnot ans:return []# 从小到大排序后,截取最大的 k 个    ans.sort()if len(ans) <= k:return ansreturn ans[-k:]defmain():    sys.setrecursionlimit(10000)    preorder = list(map(int, sys.stdin.readline().split()))    inorder = list(map(int, sys.stdin.readline().split()))    k = int(sys.stdin.readline())    res = get_top_images(preorder, inorder, k)ifnot res:        print("null")else:        print(" ".join(map(str, res)))if __name__ == "__main__":    main()