ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

华为机试高频考点与真题解析:从校招笔试到OD机考的备考指南

华为机试高频考点与真题解析:从校招笔试到OD机考的备考指南 华为2016校园招聘上机笔试题放到今天来看也依然有很强的参考价值。这几年华为的招聘流程从传统校招延伸到OD体系机试题目从单场笔试演变成双机位监考的在线考试题库也越来越体系化但核心的考察逻辑并没有变字符串处理、基础数据结构、经典算法模型、边界条件考虑、以及在一小时内把一个题目稳稳AC的能力。这篇文章不打算泛泛而谈“华为笔试有多难”而是直接把当年的题目风格、高频考点、经典真题解法、上机环境的坑、以及现在OD机考和当年笔试的传承关系全部拆开讲清楚。无论你是准备投华为校招还是打算走OD路径或者只是想把编程基础打牢这篇内容都能给你一个很明确的刷题方向。1. 2016年华为上机笔试形制与出题风格还原先说当年的考试形式。2016年华为校园招聘的技术岗笔试软件开发类岗位普遍是线上笔试加线下机考结合的方式线上笔试以选择题为主考察计算机基础、数据结构、网络等知识真正决定能否进入面试环节的是后面那场上机编程考试。总共时间一般给两个小时题目数量在不同批次略有浮动但主流是三道编程大题部分批次还会有一道附加题。语言方面当时支持C/C和JavaPython还没有像现在这样成为主流选项所以那个年代流传出来的题解大多以C/C为主。1.1 出题风格场景化题干工程化思维华为的机考题有一个很突出的特点就是题干喜欢包装成工程场景。同样是考字符串处理一般的OJ会直接写“输入一个字符串输出逆序字符串”华为会写成“在某通信设备的日志解析模块中需要将一条日志中的单词顺序反转输入为一行字符串单词间以空格分隔要求输出反转后的字符串”。这种包装不是故意绕弯子而是华为很多岗位日常确实要做日志解析、报文处理、配置文本生成这一类工作所以题目其实是在模拟真实的开发场景。相比ACM竞赛题那种“给定一棵树求树上所有路径的异或和”的风格华为的题更接地气算法难度普遍在LeetCode中等偏下但非常注重代码的完整性和规范性。很多时候你觉得题目简单结果WA了好几次往往不是算法问题而是没考虑到空串、多空格、首尾空格、超长输入这类边界情况。1.2 阅卷方式跑用例给分AC率和边缘用例决定结果华为的机考判题系统和主流OJ一样通过底层跑测试用例来判定成绩不看代码风格只看输出是否匹配。这里有个很关键的信息华为机考的测试用例分成两部分一部分是公开样例在题目描述里能看到另一部分是隐藏用例专门用来卡边界。举个实际例子有一道题要求统计字符串中每个字符出现的次数按ASCII码升序输出。公开样例给的输入是“hello world”看起来很简单。隐藏用例里可能会出现空输入可能出现全角空格可能包含换行符甚至可能出现超过int范围的输入长度。很多人在公开样例上跑通了就直接提交结果隐藏用例挂掉这就是上机考试最常见的失分点。所以我在后面会专门用一个章节来梳理这些边界套路。1.3 当年题目难度分布基础为主压轴题拉差距按照当时考生流传出来的复盘信息第一题通常是基础字符串或数组操作属于送分题第二题会稍微绕一点常用到哈希思想、排序或简单的数学逻辑第三题就是拉开差距的题常见一维动态规划、贪心、栈和队列的复杂应用、或者需要自己设计数据结构的模拟题。三道题都AC的人很少大部分人能完整AC前两道第三题拿部分分。这和现在的OD机考题目分布其实很相似只是OD机考的题目从题库中随机抽取难度波动更大而且C卷题目有时候会直接出到中等偏上的算法题所以现在很多人刷题会专门研究动态规划和图论。但2016年那会儿校招机考还比较克制动态规划也就考到最长连续子序列和这个级别不会往背包问题、区间DP那种方向塞。这也是那年题目对后来人比较友好的原因之一。2. 高频考点拆解字符串处理背后的工程思维如果你把所有华为历年机考题放在一起统计出现频率最高的不是动态规划不是图论而是字符串处理。这不是偶然。通信设备、网络管理、日志系统、配置解析所有场景的底层都是字符串操作。华为考字符串题目本质上是在考察一个人面对非结构化文本时能不能写出健壮的解析逻辑。2.1 字符统计、去重与排序一题覆盖三个基础能力“统计一行输入中各个字符出现的次数”这类题几乎是华为笔试的常客。它考的不是API调用而是三个基础能力一是能不能想到用数组下标做哈希把字符的ASCII码映射到计数数组二是能否按题目要求的顺序输出很多版本要求按ASCII码升序输出这其实就省去了排序直接遍历计数数组即可三是能否正确处理输入中的空格和换行不同语言的处理方式差异很大。这道题的工程映射非常明确日志分析中经常要统计某个字符或某个单词的出现频率比如统计一条日志里ERROR级别出现的次数或者统计某个IP地址出现在访问日志里的频率。如果你在机考时只会用map硬撸不会用数组哈希那在面对性能稍高的场景时就会吃亏。2.2 单词反转与字符串分割考察输入解析的严谨性“给出一句英文把句子中的单词顺序反转但单词内部字母顺序不变。”这道题在华为校招笔试中的出现频率极高2016年多个批次都考到了。解题思路通常是三步先反转整个字符串再逐个单词反转回正确顺序最后处理多余空格。这个思路本身不难但真正考察的是你对指针或索引边界的控制能力。多一个空格、少一个空格结果就完全不同。我当时见过不少人用Java的split方法直接切分然后逆序拼接。这种做法在单词间只有一个空格时没问题但如果输入是“hello world”两个空格split不加正则参数就会产生空字符串输出就会多出分隔符或者空元素。C语言没有现成的split很多人就用strtok而strtok会直接修改原字符串且把连续分隔符当成一个处理如果你的题目要求保留原始空格数那strtok也会出错。所以这道题别看简单细节能考倒一大片。2.3 进制转换、IP地址校验通信行业特色的隐藏考点字符串处理里还有一类带有华为特色的题目进制转换、IP地址合法性校验、子网掩码计算。华为做通信设备出身网管系统、路由协议配置、设备MAC地址处理都涉及这类逻辑。所以机考题里出现“判断一个IPv4地址是否合法”“将十进制IP转换为二进制”“将MAC地址格式标准化”这类题目是非常有行业背景的。这类题目的难点不在算法而在于你对格式规则的掌握。比如IPv4地址校验需要检查是否四段、每段是否为数字、范围是否在0到255之间、是否有前导零这个要看题目要求、是否有非法字符。很多人在校招笔试时挂在这类题上不是因为不会写代码而是因为没考虑到“01.2.3.4”这种字符串到底算不算合法地址。华为的判题系统在这方面是有明确答案的所以做题前一定要仔细读题干题干没说允许前导零那就按不允许处理。3. 经典真题复盘四道代表性题目的完整解法下面进入整篇文章最有实操价值的部分。我根据华为往年考生流传的题目回忆结合出题逻辑还原了几道最具有代表性的机考题并给出可以直接套用的C语言解法。之所以用C语言是因为2016年华为笔试主流的考生语言就是C而且C语言的解法能让你最清楚地看到内存和边界处理的过程这些经验可以平移到任何语言。3.1 单词反转不能只会split要能处理多空格题目描述还原版输入一行英文句子单词之间由一个或多个空格分隔要求将句中单词顺序反转后输出单词内部字母顺序保持不变输出的单词之间用一个空格分隔首尾不输出多余空格。这道题的难点全在空格处理上。如果只针对单个空格最简单的做法是从后往前扫描遇到空格就输出一个单词。但一旦出现多个连续空格从后往前扫就会输出空串。一个更稳妥的思路是先在原字符串上完成单词级反转然后再统一清洗空格。#include stdio.h #include string.h void reverse(char *s, int start, int end) { while (start end) { char tmp s[start]; s[start] s[end]; s[end] tmp; start; end--; } } void reverseWords(char *s) { int len strlen(s); // 第一步反转整个字符串 reverse(s, 0, len - 1); // 第二步逐个单词再反转 int i 0; while (i len) { if (s[i] ! ) { int start i; while (i len s[i] ! ) { i; } reverse(s, start, i - 1); } else { i; } } // 第三步压缩空格去掉首尾多余空格 int write 0; int read 0; while (read len s[read] ) { read; // 跳过开头的空格 } while (read len) { if (s[read] ! ) { s[write] s[read]; } else { // 遇到空格只保留一个且后面必须有非空格字符 while (read len s[read] ) { read; } if (read len) { s[write] ; } } } s[write] \0; } int main() { char s[1024]; while (gets(s) ! NULL) { reverseWords(s); printf(%s\n, s); } return 0; }这个解法有几点值得注意。第一reverse函数用的是双指针从两端向中间交换字符这个操作在C语言里非常常用。第二单词反转完成后字符串里可能还有连续空格所以必须清洗。第三gets(s)可以直接读取带空格的整行但要注意gets在C11标准里已经废弃了正式考试如果是在老环境里用没什么问题但在新环境里建议用fgets(s, sizeof(s), stdin)并手动去掉末尾换行符。3.2 字符频率统计数组哈希比map更稳题目描述还原版输入一行字符串包含大小写字母、数字和空格统计每个字符出现的次数按ASCII码从小到大输出出现过的字符及其次数每行一组格式为“字符:次数”。#include stdio.h #include string.h int main() { char line[2048]; int count[256] {0}; while (fgets(line, sizeof(line), stdin) ! NULL) { memset(count, 0, sizeof(count)); // 去掉末尾换行符 int len strlen(line); if (len 0 line[len - 1] \n) { line[len - 1] \0; len--; } for (int i 0; i len; i) { count[(unsigned char)line[i]]; } for (int i 0; i 256; i) { if (count[i] 0) { printf(%c:%d\n, i, count[i]); } } } return 0; }这道题最核心的思维方式就是利用字符的ASCII码作为数组下标建立一个长度为256的计数数组。这里有一个很多新手会踩的坑count[line[i]]中如果line[i]是char类型且为负数因为char默认可能带符号那么数组下标就变成负数了。所以一定要用(unsigned char)强制转换或者直接把count数组声明的大一点用count[(int)(unsigned char)line[i]]。这在处理扩展ASCII字符或二进制数据时尤其重要。3.3 最大连续子序列和一维DP是每年必考题型题目描述还原版给定一个整数数组数组中有正数也有负数求所有连续子序列中和最大的值并输出该最大值。如果数组长度为0输出0。这是算法题中非常经典的Kadane算法题也是华为机考动态规划考点的标配。思路是假设以第i个元素结尾的子序列最大和为dp[i]那么dp[i] max(dp[i-1] arr[i], arr[i])。也就是说如果前面的累加和加上当前元素还不如当前元素本身大那就从当前元素重新开始累加。#include stdio.h int maxSubArraySum(int arr[], int n) { if (n 0) { return 0; } int maxSoFar arr[0]; int maxEndingHere arr[0]; for (int i 1; i n; i) { if (maxEndingHere arr[i] arr[i]) { maxEndingHere maxEndingHere arr[i]; } else { maxEndingHere arr[i]; } if (maxEndingHere maxSoFar) { maxSoFar maxEndingHere; } } return maxSoFar; } int main() { int n; // 华为机考常有多种输入格式这里按先读长度再读数组处理 while (scanf(%d, n) ! EOF) { if (n 0) { printf(0\n); continue; } int arr[1000]; for (int i 0; i n; i) { scanf(%d, arr[i]); } printf(%d\n, maxSubArraySum(arr, n)); } return 0; }如果不理解Kadane算法很多人第一反应是双重循环枚举所有子序列复杂度O(n²)。在n达到几千甚至上万时就会超时。而Kadane算法把一维DP压缩成只依赖前一个状态的滚动变量时间复杂度降到O(n)空间复杂度降到O(1)。这个从O(n²)到O(n)的优化正是面试官希望在代码里看到的东西。3.4 括号匹配栈是最直观的解题工具题目描述还原版输入一个只包含()、[]、{}六种字符的字符串判断括号是否正确闭合。正确闭合的要求是括号顺序正确、类型匹配例如([])合法而([)]非法。#include stdio.h #include string.h #define MAX_SIZE 1000 int isValid(char *s) { char stack[MAX_SIZE]; int top -1; int len strlen(s); for (int i 0; i len; i) { char ch s[i]; if (ch ( || ch [ || ch {) { stack[top] ch; } else { if (top -1) { return 0; } char topChar stack[top]; if ((ch ) topChar () || (ch ] topChar [) || (ch } topChar {)) { top--; } else { return 0; } } } return top -1; } int main() { char s[MAX_SIZE]; while (scanf(%s, s) ! EOF) { printf(%s\n, isValid(s) ? YES : NO); } return 0; }括号匹配这道题考的不仅仅是栈的用法更考你对“匹配规则”的理解。([)]这种字符串虽然左右括号数量相等但交叉嵌套是错的用栈一眼就能识别。工程中配置文件的解析、表达式求值、IDE的语法高亮底层都会用到这种括号匹配逻辑。所以这道题的工程映射也非常直接它不是一道纯应付考试的题。另外一个细节是如果字符串长度上限很大比如开到10万那么用固定数组当栈就会出现越界。好在华为机考的常规题目数据范围不会太夸张但如果字符串长度可以达到10^6级别就需要用动态队列或者指针管理内存。做题前可以先估计一下数据范围再决定数组开多大。4. 上机实战的隐形门槛环境、输入输出与判题规则很多人在牛客、LeetCode上刷题时感觉良好但一到华为的机考平台就发挥失常。原因往往不是算法能力不行而是不熟悉上机环境的输入输出要求以及没有形成稳定的答题套路。4.1 输入输出格式是最容易被忽略的失分点华为上机题大多数支持多组测试用例也就是说程序需要循环读取输入直到EOF。很多考生只处理了一组输入提交后只过了公开样例隐藏用例全军覆没。比如用C语言的scanf读取就应该写成while (scanf(%d, n) ! EOF)而不是只写一次scanf(%d, n);。用Java的同学要注意用while (in.hasNextInt())或while (in.hasNextLine())。字符串读取更要小心。如果一行里有空格用scanf(%s)只能读到空格前的部分这时必须用gets()或fgets()来读取整行。C语言中gets()随着C11标准被废弃在部分新平台上可能无法编译所以更稳妥的做法是使用fgets读取后手动去除末尾换行符。char s[2048]; if (fgets(s, sizeof(s), stdin) ! NULL) { int len strlen(s); if (len 0 s[len - 1] \n) { s[len - 1] \0; } }4.2 边界条件自查清单空输入、单元素、超大值这里整理一份我在实际做题中总结的边界条件自查清单每写完一道题都按这个清单过一遍能极大提升通过率。输入为空时程序是否能正常输出不崩溃。字符串长度为1时循环边界是否正确。数组只有一个元素时最大值、最小值初始化是否合理。全为正数、全为负数时算法是否还能得到正确结果。输入字符串包含空格、换行、制表符时读取方式是否正确。整型运算是否会溢出比如求两个大数之和时是否该用long long。输出格式是否完全匹配包括空格、换行、大小写、末尾换行。以最大连续子序列和为例如果数组全为负数标准Kadane算法会返回最大的那个负数而不是返回0。题目如果没有特别说明“允许结果为负”那输出负数就是正确的。但如果你把maxSoFar初始化为0那全负数的情况下就会错误地输出0。这种坑极其隐蔽也是隐藏用例的重点关照对象。4.3 多练“裸写”能力不要过度依赖IDE提示华为上机考试支持的主流IDE是VS和Eclipse等有代码补全但考场上时间紧张而且有的线上笔试系统没有代码提示。我见过不少考生在本地IDE里写代码如鱼得水一到笔试平台的在线编辑器就手足无措连头文件都拼不完整。所以考前一定要在OJ平台上实际练习几道题尽量用在线编辑器写代码不要全程依赖IDE补全。另外一个实用技巧是提前准备好常用代码模板。包括fgets读取整行并去换行、多组输入循环、快速排序的写法、栈和队列的手写实现、以及大数组的全局声明方式。把这些模板练到肌肉记忆考试时就可以把更多的精力放在解题思路上。4.4 时间分配与提交策略先保底再优化两道小时的时间如果三道题都能AC当然最好但现实中很多人卡在第三题上。我的建议是先快速扫三题找一道最有把握的题完整AC再回头攻其他的。千万不要在第一题上反复优化浪费时间。很多人在第一题已经AC之后还花20分钟尝试换一种更高级的写法结果第二题都没写完这是最不值得的。第三题如果完全没思路也应该写上暴力解法。华为OJ按测试用例比例给分暴力解法至少能通过20%到40%的基础用例这比交白卷强得多。如果你连暴力解法都写不完那就把思路写进注释里评卷人有时候会看代码注释这虽然不保证加分但至少能展示你的思考过程。5. 从校招笔试到OD机试同一套考核逻辑的演变这几年网上关于“华为OD机试”的讨论热度很高很多人都分不清华为校招笔试和OD机考的区别。简单说它们逻辑上一脉相承但OD机考的平台化、题库化、监控化程度更高了。5.1 OD机试的双机位监考与题库目录现在的华为OD机试普遍采用双机位在线考试一个机位对准考生正面一个机位拍摄手部和屏幕监控代码是否存在抄袭或作弊行为。题目从题库中随机抽取按C卷、D卷等组织。网上流传的“华为OD机试真题题库”“机考算法考点详解”等资料本质上就是对题库中高频题目的归类整理核心考点依然集中在字符串、动态规划、栈、队列、贪心、图论搜索这几大板块。如果你现在准备的是OD机试用2016年校招笔试的真题来做基础训练完全没有问题。题目形式更加标准化了判题规则更加严格了但考察的计算思维是不变的。反过来如果你准备的是传统的校招研发岗把OD机试的高频题刷一遍对提升编程能力也有很大帮助。5.2 华为网络与硬件方向的延伸考核这里要额外提一句并不是所有华为岗位都考编程题。数通方向、网络运维方向、硬件方向的考核体系不一样。比如软件岗位机考考代码但数通方向更看重华为设备配置能力像交换机VLAN划分、端口镜像、链路聚合、堆叠配置、防火墙HRP实验这些都是实操考核内容。硬件方向会有单板硬件机考涉及ASIC、时序分析等内容。所以准备华为笔试之前先搞清楚自己投的是哪个岗位再针对性备考。软件研发岗花大量时间背交换机配置命令就是南辕北辙。网上那些“华为交换机配置实例”“华为防火墙HRP实验”的教程对应的是数通认证和网络岗位的考试需求不是通用软件岗的机考范围。5.3 备考路线不是刷得越多越好而是覆盖高频模型结合我在实际辅导中的经验如果目标是校招或OD机考备考路线不需要铺得太广重点覆盖以下几类题目就够了字符串处理反转、统计、去重、子串查找。线性数据结构栈实现括号匹配、队列模拟、链表反转。排序与查找快排、归并排序思想、二分查找。哈希与计数数组哈希、HashMap在统计题中的应用。一维DP最大子段和、爬楼梯、斐波那契变体。图论基础BFS和DFS常见于迷宫最短路径、岛屿数量等题。把这些题刷熟比你盲目刷300道难题管用得多。很多人觉得华为笔试难其实难的不是题目本身而是不熟悉这种“工程场景边界用例”的组合考察方式。当你刷题时养成了先想边界、再写代码、最后自查的习惯上机考试基本上就稳了。最后再分享一个我自己的经验练习写代码时尽量用同一套模板和风格。比如输入读取就固定用fgets或scanf的模式数组定义就固定用全局变量加const int MAXN。程序员的代码风格一旦稳定下来手速和准确率都会明显提升。考试和刷题本质上都是重复劳动的积累把基础模型练到条件反射考场上你才能把精力留给真正有挑战的题目。
返回列表