ARTICLE · 1234266
华为机考非AI方向10月23日笔试题与解析
写在前面
本次给大家带来2026年10月23日华为非AI笔试题的3道题,涉及到的岗位是:通软,嵌软,测试,普通算法(岗位名中不包含AI)以及数据科学,考试内容和报考部门无关,只和岗位有关。
需要我整理的机考一周速成题单可访问文章底部左侧:阅读原文
每周2举行华为机考公开模拟赛,自主命题,贴合考点,欢迎各位参与。
第1题-按序分苹果(150分)
题目内容
园长阿姨手里捧着 个苹果,分量各不相同,从左到右的重量记作 。班里有 个小朋友,按学号从前往后站成一行。这些苹果要顺着站位发下去,规则有两条:
不许剩下:每个人至少领一个,苹果也要全部发出去。 尽量匀一些:每个人领到的分量之和要彼此靠近。
请给出一个最小的数。它是所有发法里,各人拿到的总重量中最大的那一份,再把这个最大份压到最低。
换句话说,每种发法先记下最沉的那一份,再在这些记录当中取最小的一个。
苹果必须维持现在的左右次序,只能从左往右切成 段连续苹果。第 段交给站在最前的小朋友,后面各段按站位依次往后交。不相邻的苹果不能抽出来交给同一个人。
举个小例子。三个苹果重量是 ,发给 个小朋友。切成 与 ,两份是 和 ,最沉的是 ;切成 与 ,两份是 和 ,最沉的是 。所以最低能压到 。
输入描述
第一行给出两个整数 和 。 是苹果有多少个, 是小朋友有多少人。 第二行给出 个整数 ,按从左到右的次序写每个苹果的重量。
数据范围:
输出描述
只写出一个整数,表示最沉那一份能够压到的最小重量。
样例1
输入
4 34 1 5 2输出
5说明
要切成 段,只能在相邻苹果之间下刀。
,三份是 、、,最沉 。 ,三份是 、、,最沉 。 ,三份是 、、,最沉 。
最低能压到 ,对应最后一种切法。
题解
解题思路
苹果必须维持从左到右的次序,切成 段,每一段都是连续的若干只,每只苹果恰好进入一段。要让各段重量里最大的那一段尽量轻。
记这个最沉段的重量上限为 。 具有单调性:某个值能装下,比它更大的值也一定能装下。因此可以在区间上二分,找出最小的可行 。
二分的下界是最重的一只苹果,因为单独一段也至少要装下它。上界是全部苹果的总重量,对应只切成一段。
检查某个 是否可行时,从左往右贪心装袋:
若某一只苹果本身重于 ,这个上限直接失败。 当前段再放一只就会超过 时,立刻新开一段,并从这只苹果重新累加。 扫完后段数不超过 ,则 可行。
固定上限时,当前段能多装就多装。提前切开只会浪费这段剩余容量,后面的苹果顺序又不能调,段数不会因此变少。所以贪心得到的段数就是该上限下最少需要的段数。
正数重量下,少用几段只会让某一段更沉,所以「段数不超过 」和「恰好切成 段」得到同一个最小最沉份。
复杂度分析
二分最多进行 轮,其中 是总重量,不超过 。每轮把 只苹果扫一遍。总时间复杂度是 ,额外空间复杂度是 。
代码实现
读入放在主函数里,切分放在单独的函数里。五份代码是同一套二分加贪心。
python代码(C++和JAVA代码见在线OJ网址)
# 把一排苹果按原顺序切成若干段,让最沉那一段尽量轻。# 重量上限一旦可行,更大的上限也一定可行,所以对上限做二分。defmin_peak(count, groups, weights):"""返回把 weights 切成恰好 groups 段时,各段重量最大值的最小值。"""defpackable(limit):"""判断能否让每一段的重量都不超过 limit。"""# 单只苹果比上限还沉,这一段怎么切都装不下。# 从左往右累加;再放一只就会超限时,必须新开一段。# 新段从当前这只苹果开始,保证段与段首尾相接、中间不空。 used = 1 acc = 0for w in weights:if w > limit:returnFalseif acc + w > limit: used += 1 acc = welse: acc += w# 人数不够装下这么多段,这个上限不可行。return used <= groups# 最沉的一段至少要能装下最重的一只苹果,也至多是全部苹果的总重。 low = max(weights) high = sum(weights)# 二分可行的最小上限。count 只用来和读入对齐,切分本身只看 weights 与 groups。if count != len(weights):raise ValueError("apple count mismatch")while low < high: mid = (low + high) // 2if packable(mid): high = midelse: low = mid + 1return lowdefmain():# 读入苹果个数和小朋友人数。 first = input().split() count = int(first[0]) groups = int(first[1])# 第二行是从左到右每只苹果的重量。 weights = list(map(int, input().split()))# 输出最沉那一段能压到的最小重量。 print(min_peak(count, groups, weights))if __name__ == "__main__": main()第2题-机器调度模拟(150分)
题目内容
一共有 项任务要在一台机器上跑完。每项任务带四个量:编号 (互不相同)、优先等级 (数值更大者更靠前)、抵达时刻 、所需时长 。这台机器在任一时刻至多跑一项任务。
调度约定如下。机器一旦空闲,就马上从等候队列里挑一项开始跑;时长 的任务,只要被挑中,就在该时刻立刻结束。某项任务还在跑时,若又有任务抵达,只有新来者的 比正在跑的这项更大,才允许把当前这项挤下去;被挤下去的任务把还没跑完的时间留下来,再放回等候队列。挑下一项时按三层次序比较,从而只有一个结果: 从大到小, 从早到晚,读入时的先后从先到后。被挤下去后再放回队列时,、 和读入先后都保持原来的值,不会改成发生挤占的那个时刻。结束与抵达如果落在同一个时刻,必须先把结束处理完,再把这个时刻抵达的任务收进队列,之后才挑下一项。
解答要求
C 与 C++ 的运行时间上限为 毫秒,其余语言放宽到 毫秒。
C 与 C++ 最多占用 兆字节,其余语言最多占用 兆字节。
输入描述
首行一个整数 。后面共有 行,每一行写下四个整数 ,顺次是这项任务的编号、优先等级、抵达时刻和所需时长。各个 彼此不同,读入行的先后会参与挑选时的比较。
输出描述
只用一行写出 个 ,按结束的先后排好,相邻两个之间隔一个空格。
约束
,,,。时刻的加减使用 位有符号整数。
样例1
输入
47 2 0 89 5 3 24 5 3 48 1 6 3输出
9 4 7 8说明
四项任务按读入先后,编号是 、、、。
时刻 :编号 抵达,队列里只有它,于是开跑,还要跑 。 时刻 :编号 与编号 一同抵达。两者等级都是 ,高于正在跑的 ;编号 在输入里更靠前,所以把编号 挤下去。编号 已跑 ,还剩 ,等级和抵达时刻仍是 与 。编号 开跑,时长 。 时刻 :编号 结束。还在等的是编号 (等级 )和编号 (等级 ),先跑编号 。 时刻 :编号 抵达,等级 并不高于正在跑的 ,只能排队。 时刻 :编号 结束。编号 的等级高于编号 ,接着把剩下的 跑完。 时刻 :编号 结束,编号 开始,再过 结束。
结束顺序是 。
题解
解题思路
一台机器要跑完 项任务。每项任务有编号 、优先等级 、抵达时刻 和所需时长 。输出这些编号结束的先后。
用事件模拟,不用逐个时间单位往前走。机器上的决定只在两种时刻发生变化:有新任务抵达,或者当前任务刚好跑完。两个事件之间,正在跑的任务只是把剩余时间减少。时刻用 位整数保存,因为全部任务接连跑完时,结束时刻可以到大约 。
还没结束、也不在机器上的任务放进堆。堆顶是当前最该跑的一项。比较顺序是 从大到小,再比 从早到晚,最后比读入下标从小到大。三个键一起比较,挑选结果只有一个。等级按原值比较,这样 也能正确进堆。
每个事件时刻按固定顺序处理。先把正在跑的任务的剩余时间减到当前时刻;若剩余已经是 ,先把它记入结束序列。再把这个时刻抵达的任务全部放进堆。若堆顶的等级严格大于正在跑的任务,才把正在跑的任务连同剩余时间放回堆,它的等级、抵达时刻和读入下标都保持原值。最后如果机器空着,就反复取出堆顶:时长为 的当场结束并继续取,直到取出一项时长为正的任务,或堆已经空了。
一次抵达至多把当前正在跑的那一项挤下去。因此全部任务进出堆的总次数是 ,不会因为反复挤占变成平方次。
复杂度分析
时间复杂度:。按抵达时刻排序是 ,之后每次入堆或出堆都是 ,这些操作的总次数是 。 空间复杂度:。任务表、抵达顺序和堆都与任务数成正比。
代码实现
读入写在主函数里,调度过程放在单独的函数里。五份代码是同一套事件模拟。
python代码(C++和JAVA代码见在线OJ网址)
import heapqdeffinish_order(tasks): n = len(tasks) order = sorted(range(n), key=lambda i: (tasks[i][2], i)) heap = [] # (-等级, 抵达时刻, 读入下标, 剩余时长, 编号) ptr = now = 0 run = None ans = [] inf = 10 ** 18while len(ans) < n: nxt = tasks[order[ptr]][2] if ptr < n else infif run isNone:if nxt == inf:break moment = nxtelse: moment = min(nxt, now + run[4]) run[4] -= moment - now now = moment# 同一时刻先结束,再把此刻抵达的任务放进堆。if run isnotNoneand run[4] == 0: ans.append(run[0]) run = Nonewhile ptr < n and tasks[order[ptr]][2] == now: i = order[ptr] k, r, s, d = tasks[i] heapq.heappush(heap, (-r, s, i, d, k)) ptr += 1# 等级严格更高才挤占;放回堆时不改等级、抵达时刻和读入下标。if run isnotNoneand heap and -heap[0][0] > run[1]: k, r, s, i, left = run heapq.heappush(heap, (-r, s, i, left, k)) run = Nonewhile run isNoneand heap: neg, s, i, left, k = heapq.heappop(heap)if left == 0: ans.append(k)else: run = [k, -neg, s, i, left]breakreturn ansdefmain(): n = int(input()) tasks = [tuple(map(int, input().split())) for _ in range(n)] print(*finish_order(tasks))if __name__ == "__main__": main()第3题-AI Agent管理(300分)
题目内容
小华平时要带着 名 AI Agent 一起赶一个项目。项目规模按代码行来计,一共是 行 Loc。他打算把这些行数拆给不同的 AI Agent,并让自己用来交代任务的时间尽量短。
AI Agent 听得懂自然语言。小华把需求讲完,再交由它去完成。
一名 AI Agent 好不好用,由下面三个量决定:
委托效率:小华对着这名 AI Agent 讲需求、对齐方案时,它每分钟能消化并记住的代码行数,记作 行每分钟。 最低消费:模型调用的费用由小华自己付。为了吃到便宜套餐,一旦启用这名 AI Agent,购买时长不能短于 分钟。 最高消费:各家模型单价不同,小华给每名 AI Agent 卡了花费上限,购买时长不能长于 分钟。
再补三条:
小华在意的是自己何时能把任务全部交代完、从而空出手,并不在意项目最终哪一天收尾。所以各名 AI Agent 谁先谁后都无所谓。 交互效率保持不变,多出来的额度可以闲置。已购买的套餐能覆盖的代码行数达到 行即可。 同一时刻小华只能跟一名 AI Agent 交谈,任务得一个一个交代。
请给出购买方案,使这些套餐覆盖的行数不少于 ,并且购买分钟数之和最小。输出这个最小的分钟数。
输入描述
第一行是两个整数 和 。 表示 AI Agent 有几名, 表示项目一共有多少行 Loc。 其后 行,每一行三个整数 、、。这三个数按顺序对应该名 AI Agent 的委托效率、它的最低消费,以及它的最高消费。
数据范围:
输出描述
输出一个整数,表示覆盖全部行数所需购买分钟数的最小值。若把每名 AI Agent 都买到最高消费仍不够,则输出 。
样例1
输入
2 200009000 3 84000 2 6输出
3说明
效率 的那名至少买 分钟,得到 行,已经盖过 行,用时 分钟。另一名要买满 分钟才够 行。因此最少是 分钟。
题解
解题思路
每名 AI Agent 要么不买,要么购买的分钟数落在 里。总时间是各人分钟之和。覆盖行数达到 即可。 的代理买不了。
先按效率从高到低买出一个可行方案,把它的总分钟记为 。最优答案不会超过 。
表示恰好花 分钟能完成的最大行数。加入一名效率为 、区间为 的代理时,不买就保持上一轮的 ;若上一轮花了 分钟,且 ,新行数是 。也就是在下标区间 里找 最大的 ,再用双端队列维护这个滑动窗口。
最小的满足 的 就是答案。全部买到最高消费仍不够时,答案是 。
复杂度分析
时间复杂度是 ,空间复杂度是 。 不超过全部最高消费之和。
代码实现
python代码(C++和JAVA代码见在线OJ网址)
from collections import dequedefmin_minutes(C, G, agents):"""返回覆盖 G 行所需的最少分钟,做不到时返回 -1。""" items = [] total = 0for e, u, v in agents:# 最低消费比最高消费大,这名代理买不了。if u <= v: items.append((e, u, v)) total += e * vif G <= 0:return0if total < G:return-1# 按效率从高到低凑一个可行方案,H 是它的总分钟,也是 DP 上界。 remain, H = G, 0for e, u, v in sorted(items, key=lambda x: -x[0]):if remain <= 0:break need = (remain + e - 1) // e take = min(v, max(u, need)) H += take remain -= e * take# dp[t]:恰好花 t 分钟能完成的最大行数。 dp = [-1] * (H + 1) dp[0] = 0for e, u, v in items: old = dp[:] que = deque() added = -1for t in range(H + 1): right, left = t - u, t - v# 窗口 [t-v, t-u] 中,old[s] - e*s 最大的 s 最划算。while added < right: added += 1if added >= 0and old[added] >= 0:while que and old[que[-1]] - e * que[-1] <= old[added] - e * added: que.pop() que.append(added)while que and que[0] < left: que.popleft()if que and que[0] <= right: s = que[0] got = old[s] + e * (t - s)if got > dp[t]: dp[t] = gotfor t in range(H + 1):if dp[t] >= G:return treturn-1defmain(): C, G = map(int, input().split()) agents = [tuple(map(int, input().split())) for _ in range(C)] print(min_minutes(C, G, agents))if __name__ == "__main__": main()手机端刷题:塔子哥刷题宝















































































