夜雨聆风学习资料网

ARTICLE · 1234266

华为机考非AI方向10月23日笔试题与解析

华为机考非AI方向10月23日笔试题与解析

写在前面

本次给大家带来2026年10月23日华为非AI笔试题的3道题,涉及到的岗位是:通软,嵌软,测试,普通算法(岗位名中不包含AI)以及数据科学,考试内容和报考部门无关,只和岗位有关。

需要我整理的机考一周速成题单可访问文章底部左侧:阅读原文

每周2举行华为机考公开模拟赛,自主命题,贴合考点,欢迎各位参与。

题号
题目
难度(对标leetcode)
核心做法
1
按序分苹果
中等
二分算法
2
机器调度模拟
中等
模拟
3
AI Agent管理
困难
动态规划

第1题-按序分苹果(150分)

题目内容

园长阿姨手里捧着  个苹果,分量各不相同,从左到右的重量记作 。班里有  个小朋友,按学号从前往后站成一行。这些苹果要顺着站位发下去,规则有两条:

  1. 不许剩下:每个人至少领一个,苹果也要全部发出去。
  2. 尽量匀一些:每个人领到的分量之和要彼此靠近。

请给出一个最小的数。它是所有发法里,各人拿到的总重量中最大的那一份,再把这个最大份压到最低。

换句话说,每种发法先记下最沉的那一份,再在这些记录当中取最小的一个。

苹果必须维持现在的左右次序,只能从左往右切成  段连续苹果。第  段交给站在最前的小朋友,后面各段按站位依次往后交。不相邻的苹果不能抽出来交给同一个人。

举个小例子。三个苹果重量是 ,发给  个小朋友。切成  与 ,两份是  和 ,最沉的是 ;切成  与 ,两份是  和 ,最沉的是 。所以最低能压到 。

输入描述

  • 第一行给出两个整数  和 。 是苹果有多少个, 是小朋友有多少人。
  • 第二行给出  个整数 ,按从左到右的次序写每个苹果的重量。

数据范围:

输出描述

只写出一个整数,表示最沉那一份能够压到的最小重量。

样例1

输入

4 34 1 5 2

输出

5

说明

要切成  段,只能在相邻苹果之间下刀。

  • ,三份是 、、,最沉 。
  • ,三份是 、、,最沉 。
  • ,三份是 、、,最沉 。

最低能压到 ,对应最后一种切法。

题解

解题思路

苹果必须维持从左到右的次序,切成  段,每一段都是连续的若干只,每只苹果恰好进入一段。要让各段重量里最大的那一段尽量轻。

记这个最沉段的重量上限为 。 具有单调性:某个值能装下,比它更大的值也一定能装下。因此可以在区间上二分,找出最小的可行 。

二分的下界是最重的一只苹果,因为单独一段也至少要装下它。上界是全部苹果的总重量,对应只切成一段。

检查某个  是否可行时,从左往右贪心装袋:

  1. 若某一只苹果本身重于 ,这个上限直接失败。
  2. 当前段再放一只就会超过  时,立刻新开一段,并从这只苹果重新累加。
  3. 扫完后段数不超过 ,则  可行。

固定上限时,当前段能多装就多装。提前切开只会浪费这段剩余容量,后面的苹果顺序又不能调,段数不会因此变少。所以贪心得到的段数就是该上限下最少需要的段数。

正数重量下,少用几段只会让某一段更沉,所以「段数不超过 」和「恰好切成  段」得到同一个最小最沉份。

复杂度分析

二分最多进行  轮,其中  是总重量,不超过 。每轮把  只苹果扫一遍。总时间复杂度是 ,额外空间复杂度是 。

代码实现

读入放在主函数里,切分放在单独的函数里。五份代码是同一套二分加贪心。

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

说明

四项任务按读入先后,编号是 、、、。

  • 时刻 :编号  抵达,队列里只有它,于是开跑,还要跑 。
  • 时刻 :编号  与编号  一同抵达。两者等级都是 ,高于正在跑的 ;编号  在输入里更靠前,所以把编号  挤下去。编号  已跑 ,还剩 ,等级和抵达时刻仍是  与 。编号  开跑,时长 。
  • 时刻 :编号  结束。还在等的是编号 (等级 )和编号 (等级 ),先跑编号 。
  • 时刻 :编号  抵达,等级  并不高于正在跑的 ,只能排队。
  • 时刻 :编号  结束。编号  的等级高于编号 ,接着把剩下的  跑完。
  • 时刻 :编号  结束,编号  开始,再过  结束。

结束顺序是 。

题解

解题思路

一台机器要跑完  项任务。每项任务有编号 、优先等级 、抵达时刻  和所需时长 。输出这些编号结束的先后。

  1. 用事件模拟,不用逐个时间单位往前走。机器上的决定只在两种时刻发生变化:有新任务抵达,或者当前任务刚好跑完。两个事件之间,正在跑的任务只是把剩余时间减少。时刻用  位整数保存,因为全部任务接连跑完时,结束时刻可以到大约 。

  2. 还没结束、也不在机器上的任务放进堆。堆顶是当前最该跑的一项。比较顺序是  从大到小,再比  从早到晚,最后比读入下标从小到大。三个键一起比较,挑选结果只有一个。等级按原值比较,这样  也能正确进堆。

  3. 每个事件时刻按固定顺序处理。先把正在跑的任务的剩余时间减到当前时刻;若剩余已经是 ,先把它记入结束序列。再把这个时刻抵达的任务全部放进堆。若堆顶的等级严格大于正在跑的任务,才把正在跑的任务连同剩余时间放回堆,它的等级、抵达时刻和读入下标都保持原值。最后如果机器空着,就反复取出堆顶:时长为  的当场结束并继续取,直到取出一项时长为正的任务,或堆已经空了。

  4. 一次抵达至多把当前正在跑的那一项挤下去。因此全部任务进出堆的总次数是 ,不会因为反复挤占变成平方次。

复杂度分析

  • 时间复杂度:。按抵达时刻排序是 ,之后每次入堆或出堆都是 ,这些操作的总次数是 。
  • 空间复杂度:。任务表、抵达顺序和堆都与任务数成正比。

代码实现

读入写在主函数里,调度过程放在单独的函数里。五份代码是同一套事件模拟。

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()
刷题练习:CodeFun2000.com

手机端刷题:塔子哥刷题宝

相关学习资料