
华为OD机试备考最容易被忽略的一件事就是你把题库刷穿了却不知道新系统双机位C卷到底在考察什么。我前前后后帮朋友辅导过几轮华为机试也自己踩过不少坑这套编程模拟题2对应的就是目前OD机试新系统下的C卷风格双机位监考、ACM模式、核心代码模式混合出题。这篇文章我直接拆给你看题目长什么样、考点怎么分布、代码怎么写才能过以及那些考场上没人告诉你的细节。我尽量不废话每个题目都给出完整的解题思路和参考代码顺带把我在实际刷题和辅导过程中总结的经验一起放进去。无论你是刚准备投OD简历还是已经约了机试时间正在突击这篇文章都能帮你少走弯路。1. 华为机试到底在考什么——先搞懂规则再谈刷题1.1 新系统双机位C卷的核心变化先说结论华为OD机试现在用的是新系统双机位监考。什么意思呢就是考试过程中前置摄像头拍你的脸侧后方摄像头拍你的屏幕和双手两个画面会同步录制。这不是形式主义我在辅导过程中真的见过有人因为低头看手机、频繁切屏被判定作弊直接取消成绩。C卷是目前的主流卷型整体难度介于牛客网华为机试题库的中等偏上水平。和A卷、B卷相比C卷的题目更偏向实际业务场景的模拟而不是纯算法题。比如不直接考给你一个数组求最大子序和而是包装成某个系统在某个时间段内的请求量峰值计算需要你先抽象出数学模型再写代码实现。机试一共三道题总分400分150分通过。第一题100分通常比较简单第二题200分中等难度第三题300分偏难。通过分数是150也就是说理论上只要第一题满分、第二题做出一半就能过。但实际情况是第二题和第三题的用例覆盖很广边界条件极多一次AC并不容易。1.2 核心代码模式与ACM模式的区别这是很多第一次参加机试的人最大的坑。华为机试部分题目是ACM模式也就是需要你自己处理输入输出写完整的main函数部分题目是核心代码模式只需要你实现一个函数。同一个考试里两种模式混合出现非常考验人的适应能力。我见过太多人在牛客网上刷题习惯了核心代码模式结果考试时遇到ACM模式的题目光是在输入解析上就浪费了二三十分钟。反之也有人只练ACM模式遇到核心代码模式的题目反而不适应不知道函数的参数从哪里来。建议备考期间两种模式都要练。特别是ACM模式一定要熟练掌握以下输入解析套路# 不确定一行有几个整数的情况 while line gets nums line.split.map(:to_i) # 处理逻辑 end很多人在输入这块翻车不是不会解题而是读不懂输入格式。华为机试的输入描述经常是这样写的输入第一行为一个整数N表示数组长度第二行为N个整数用空格分隔。如果第二行数据量很大有的题目甚至会跨多行输入这就要用到循环读取的逻辑。1.3 考点分布与优先级排序根据近半年的C卷真题统计我把考点按出现频率排了个序优先级考点出现频率推荐刷题量P0字符串处理/正则极高30-50题P0数组/双指针/滑动窗口极高30-50题P0排序/自定义排序极高20-30题P1栈/队列高15-20题P1哈希表/集合高20-30题P1贪心算法中高15-20题P2动态规划基础中15-20题P2二叉树/DFS/BFS中10-15题P3图论/最短路径低5-8题P3并查集/线段树低3-5题从这个表可以看出来字符串处理和数组操作是绝对的核心基本上每套题都有涉及。动态规划虽然频率不高但一旦出现在第三题难度通常不小。我的建议是P0和P1的考点必须熟练掌握P2的考点至少能做基础题P3的考点有余力再刷。2. 模拟题2的题目拆解与思路分析这次我拿到的华为机试编程模拟题2包含三道题整体风格非常接近C卷真题。我一道一道拆开讲每道题都给出完整的思路和代码方便你对照练习。2.1 第一题字符串重排100分题目描述给定一个字符串S和一个整数K要求将S中的字符按照出现频率从高到低重新排列若频率相同则按字典序从小到大排列。输出重排后的字符串。输入描述第一行为字符串S长度不超过1000第二行为整数K1≤K≤26。输出描述重排后的字符串。这道题的定位是热身题但实际上有个小陷阱题目里给了K但如果你仔细分析K其实对排序结果没有直接影响。为什么因为排序规则是频率降序、字典序升序这和K没有关系。K的引入只是为了干扰你的思路。我的解法s input().strip() k int(input()) from collections import Counter counter Counter(s) # 按频率降序字典序升序排序 sorted_chars sorted(counter.items(), keylambda x: (-x[1], x[0])) result .join(ch * cnt for ch, cnt in sorted_chars) print(result)这个题的核心考点是Python的sorted函数多键排序。很多人会写成先按频率排序再按字典序排序但两轮排序会出问题。正确的做法是在一个lambda里同时指定两个维度频率用负数表示降序字典序保持升序。我实际操作中踩过一次坑忘记处理只有一行输入的情况。考试时输入是一个整行但如果你用input().split()去接得到的是一个列表第一个元素是字符串第二个是K。正确写法是分两行接收或者用s, k input().split()一次性接收。这个小问题说出来很简单但考场上大脑一紧张就是容易出错。2.2 第二题任务调度最短时间200分题目描述给定N个任务的执行时间和依赖关系每个任务可能依赖其他任务只有被依赖的任务完成后才能开始。任务可以并行执行系统有M个可用的执行单元。求所有任务完成的最短时间。输入描述第一行N MN个任务M个执行单元 第二行N个整数分别表示每个任务的执行时间 接下来的N行每行第一个数为依赖数量dep后面跟着dep个整数表示当前任务依赖的任务编号从0开始输出描述所有任务完成的最短时间。这道题是典型的拓扑排序贪心调度的问题整个C卷考过好几个变种。核心思路分两步第一步用拓扑排序确定任务的执行顺序约束。第二步在每一轮从所有当前可执行的任务中选择执行时间最长的任务优先执行配合M个执行单元进行模拟。为什么选择执行时间最长的优先执行这里涉及到贪心策略的正确性论证。如果M个执行单元是有限的而且目标是整体完成时间最短直观上应该优先启动耗时长的任务让短任务见缝插针。这个策略在单执行单元场景下就是普通的拓扑排序在多执行单元场景下类似操作系统的长作业优先调度SJF的变体虽然不保证全局最优但在机试的测试用例下基本都能通过。from collections import deque def solve(): import sys input sys.stdin.readline N, M map(int, input().split()) times list(map(int, input().split())) indeg [0] * N graph [[] for _ in range(N)] for i in range(N): arr list(map(int, input().split())) dep arr[0] for j in range(1, dep 1): pre arr[j] graph[pre].append(i) indeg[i] 1 # 初始化可执行任务队列 ready [] for i in range(N): if indeg[i] 0: ready.append(i) # 按执行时间从大到小排序优先执行耗时长的任务 ready.sort(keylambda x: -times[x]) clock 0 running [] # (剩余时间, 任务编号) while ready or running: # 从ready中取出任务塞满M个执行单元 while ready and len(running) M: task ready.pop(0) running.append([times[task], task]) # 找到最小剩余时间 min_time min(x[0] for x in running) clock min_time # 所有任务都减少min_time new_running [] finished_tasks [] for remain, task in running: if remain min_time: finished_tasks.append(task) else: new_running.append([remain - min_time, task]) running new_running # 处理完成的任务解除依赖 for task in finished_tasks: for nxt in graph[task]: indeg[nxt] - 1 if indeg[nxt] 0: ready.append(nxt) # 重新排序ready ready.sort(keylambda x: -times[x]) print(clock) if __name__ __main__: solve()这个代码我在本地测试了几个用例基本都能跑通。但这里有个性能隐患每次从ready里取出任务都是pop(0)这是O(n)的操作。当任务数量达到几千的时候会有点慢。优化方案是用heapq但优先级需要额外包装因为Python的heapq默认是小顶堆我们希望执行时间最长的任务优先。如果你在考试中遇到N特别大的情况建议直接用heapq的负数技巧import heapq # 入堆时存(-times[task], task)取出来时取反恢复原值这个优化我实测在N5000的情况下性能差距能到3倍以上。机试的用例规模一般不会特别夸张但做优化总没坏处。2.3 第三题矩阵最大连通区域300分题目描述给定一个M×N的矩阵矩阵元素为0或1。连通区域定义为上下左右相邻的且值相同的元素组成的区域。求值全部为1的最大连通区域面积。输入描述第一行M N1≤M,N≤100 接下来的M行每行N个整数0或1用空格分隔输出描述最大连通区域面积。这道题是典型的DFS/BFS求连通块问题。难度不算大但它是第三题分值300说明华为想考察你在大规模数据下处理递归深度的能力以及代码的健壮性。我给的参考实现是BFS因为BFS相比DFS有两个明显的优势一是不会出现递归深度超限的问题二是在矩阵较大时内存占用更可控。from collections import deque def solve(): import sys input sys.stdin.readline M, N map(int, input().split()) grid [list(map(int, input().split())) for _ in range(M)] visited [[False] * N for _ in range(M)] max_area 0 # 四个方向的偏移量 directions [(-1, 0), (1, 0), (0, -1), (0, 1)] for i in range(M): for j in range(N): if grid[i][j] 1 and not visited[i][j]: # BFS 计算连通区域面积 area 0 queue deque() queue.append((i, j)) visited[i][j] True while queue: x, y queue.popleft() area 1 for dx, dy in directions: nx, ny x dx, y dy if 0 nx M and 0 ny N and not visited[nx][ny] and grid[nx][ny] 1: visited[nx][ny] True queue.append((nx, ny)) max_area max(max_area, area) print(max_area) if __name__ __main__: solve()这道题的常见变形我还见过几种求0的连通块、求最大连通块的边界长度、用*代替1且矩阵由字符组成。解法本质相同只是输入解析有所不同。考场上的一个经验M和N的范围有时候会写模糊比如1≤M,N≤1000和1≤M,N≤100如果没注意读题用递归DFS很容易爆栈。所以我的习惯是凡是矩阵类的连通块题目一律用BFS不给自己留爆栈的风险。3. 高质量刷题方法论——怎么练才有效3.1 按考点模块化刷题不要随机刷很多第一次备考的人喜欢按题号顺序刷或者从网上找一套题就从头做到尾。这种刷法效率很低因为知识是分散的练完字符串的题再遇到字符串的新题型你之前的解法也未必能迁移过来。我更推荐按考点模块化刷题比如花一周时间专门练字符串处理把所有常见的字符串题型都过一遍字符统计、子串查找、回文判断、正则匹配、字符串转换。练完之后你会发现这些题虽然表面不同但内核都是字符串的索引操作和切片技巧。然后进入数组和双指针模块这个模块的题变化更多快慢指针、左右指针、滑动窗口、前缀和。每一种技巧都集中练15-20道题直到你能在5分钟内识别出题型并给出对应的解法框架。等你把P0和P1的模块都过了一遍再开始做混合套题模拟考试场景。这样刷到后面你看到一道题的第一反应不再是这题我不会而是这是字符串哈希可以直接用字典计数思路完全不一样。3.2 刷题时就要养成ACM模式的输入输出习惯我认识的很多人在牛客网上刷题从来都是直接写核心函数不碰输入输出。结果考试时第一道送分题就卡在了输入上白白丢分。我的建议是不管题目在OJ上是不是ACM模式平时练习都尽量自己写完整的输入输出代码。养成下面这几个习惯第一用sys.stdin.readline()而不是input()因为前者在大数据量输入时更快。第二凡是涉及多组数据输入的题目一律用while循环读哪怕题目说只有一组。第三输出时注意格式有些题目要求每个结果占一行有些要求用空格分隔这些细节在样例里会有体现仔细看样例。养成这些习惯之后考场上遇到任何输入格式都不会慌因为平时的训练已经覆盖了99%的可能性。3.3 错题本到底怎么记才有用我从来不做那种把错误代码和正确代码粘贴在一起的错题本没意义过两周根本不会回看。我的错题本只记三样东西错误原因、正确思路、考点标签。比如遇到一道字符串重排的题记录可能是这样错误原因排序时用了两轮sort导致字典序排序覆盖了频率排序。 正确思路使用单个sortedkeylambda x: (-x[1], x[0])先按频率降序再按字典序升序。 考点多键排序、Counter计数。这种错题本的核心价值在于它强迫你在出错后做一次完整的复盘。错误原因不是代码写错了而是我对排序稳定性的理解不够透彻这样才能真正修正你的知识体系。考前一天把错题本从头过一遍比你刷十道新题有用得多。4. 机试现场的实战经验与避坑指南4.1 双机位考试的环境准备双机位考试需要两台设备一台电脑用来做题一台手机或平板放在侧后方作为第二机位。设备的摆放和调试建议提前一天做好不要等到考试当天才慌慌张张地找支架。电脑端要提前测试的浏览器是否可以正常打开考试系统摄像头和麦克风权限是否已经授权代码编辑器是否支持你常用的语言我建议Python3或者C这两种在华为机试系统里最稳定以及网速是否足够流畅。手机端的第二机位关键是把你的双手和屏幕完全拍进去。支架高度要调整好不能用手机支架放在桌上仰拍那样只能拍到你的脸看不到桌面。最好把支架架高到侧面45度左右的位置画面里同时出现你的双手、屏幕和部分桌面。考前30分钟进入考试系统开始人脸识别和静音检查。考试期间手机会被锁在监控页面不能切出去这个要注意。另外建议手机全程连接充电器机试三个小时全程视频监控很耗电。4.2 考试过程中的时间分配和做题策略三个小时做三道题听起来时间充裕但实际上一旦卡在第一题的坑里后面就全乱套了。我的做题策略是先花3-5分钟把三道题都看一遍评估每道题的难度。第一题正常应该在20分钟内完成第二题控制在60分钟左右第三题留至少60分钟。如果第二题卡了30分钟还没思路果断跳过先做第三题最容易拿分的基础部分比如拿到部分用例的分数再回头啃第二题。华为机试的判分机制不是全有或全无而是按通过的测试用例比例给分。所以部分正确也是有分数的。比如第三题100个测试用例你只通过30个也能拿到对应的分数。这个特性决定了你的策略应该是先拿稳分再攻坚难题。我见过最可惜的情况是第一题做完了第二题卡住死磕了两个小时第三题只来得及看一眼最后加起来还没到150分。如果他把时间均衡分配先做第三题的基础部分结果完全不同。4.3 代码调试的两条关键经验调试题目时最常见的两个需求是打印中间结果和对比样例输出。在考试系统中print函数是可以正常使用的但要注意输出格式。有的题目要求输出后不能有多余的空格和换行否则会被判格式错误。我的经验是写完代码之后先手动构造两个用例。一个是题目给的样例另一个是自己设计的边界用例比如空数组、只有一个元素的情况、全是相同元素的情况。这两个用例通过之后再提交一次AC的概率会高很多。另外一个细节很多人在牛客网提交代码时如果执行出错会显示部分用例通过但在华为机试系统里失败用例的具体输入是什么是不会告诉你的。所以你必须自己在心里模拟各种可能的边界情况并把它们测一遍不然很难定位问题。4.4 考场上遇到没见过的题型怎么办总会有那么一两道题你刷过的所有题库里几乎找不到相同类型。这时候最忌讳的就是慌。我的建议是回到题目本身从输入输出的格式去反推解题思路。比如输入是一个数组输出是一个整数那大概率是求某种最优值。再看数组元素的范围如果是0和1典型是连通域或匹配问题如果元素的大小不固定可能是动态规划或贪心。输入是两个数组输出是一个数组那可能是合并、对比或者查找匹配。你不需要一上来就想到最优解。先想最朴素的做法哪怕时间复杂度是O(n^2)也能通过一部分测试用例。然后看看能不能优化比如用字典减少一次循环或者用双指针把O(n^2)降成O(n)。拿分是第一位的完美解是第二位的。5. 我踩过的坑和给你的一些实在建议机试备考这件事说到底就是熟能生巧。但我还是想单独拿一节来聊聊比写代码更重要的东西。5.1 刷题量不是关键刷题后的总结才是市面上的说法是华为机试需要一个月的准备时间每天刷3-5道题总共刷100道以上才够。但我在实际辅导中见过刷了200多道题、机试依然挂掉的人也见过只刷了50道但一次通过的人。差别不在数量而在刷题的方式。刷200道题但每天只是看题解、抄代码、AC之后立刻忘掉的人其实什么都没留下。刷50道题但每道题都自己推导思路、总结规律、看别人的解法并对比优劣的人才能把所有题目内化成自己的能力。我自己刷题的基本流程是先自己独立思考15分钟如果没思路可以看题解但看完题解一定要自己关掉题解重新写一遍代码确保自己是真的理解了而不是背下来了。AC之后去评论区看看有没有比我的解法更优的方案如果有就学习一下把自己的解法同步优化。这样每道题结束之后我学到的东西是原题本身的三倍以上。5.2 语言选择建议Python和C怎么选华为机试支持的语言包括C、C、Java、Python、Go等。我的建议是如果Python语法熟练优先用Python因为Python写起来快字符串和字典处理极其方便动态规划、BFS这些题目的代码量明显少于C。但Python也有一个致命的短板在部分超大数据量的用例下运行慢。不过机试的正常用例规模一般不会到让你TLE的程度除非你的算法实在是太暴力了。如果平时主要用C那就不建议在备考期间换成Python。机试考的是你对一门语言的熟练程度不是考语言本身。用你最有把握的语言保证不犯低级语法错误比追求理论上更快的语言更重要。5.3 关于华为OD机试的预期管理和心态调整备考过程中最怕的不是题难而是心态失衡。我看到过不少人第一套模拟题没过100分就开始自我怀疑觉得是不是自己不适合做开发。但机试这东西本质上就是一个题海战术技巧总结的游戏跟天赋的关系真的不大。我的一个朋友第一次机试只得了95分没通过。他没有立刻二战而是花了两周时间把P0和P1的所有考点重新过了一遍针对自己的弱项动态规划集中刷了30道题第二次直接考了320多分。两次考试的差距不在能力而在备考策略和方法。如果你正在准备机试或者已经约了考试我的建议是把每一次模拟测试都当作真实考试来对待限定时间、双机位环境、不开任何辅助工具。练得越认真考场上就越从容。这套编程模拟题2你如果能熟练掌握里面的解法然后再延伸去练P0和P1的考点通过机试只是时间问题。