
这套卷子是我一位学弟去年秋招时做到的原题回忆版前几天他回来跟我聊起我干脆把整个B卷的考察逻辑、高频考点和几道典型编程题的解题路径都拉通复盘了一遍。爱奇艺这套2019秋招C方向笔试题B放在今天看依然是很有代表性的互联网公司C/C岗位笔试题——不偏不怪难度中等偏上但覆盖面特别广很适合拿来当C语言和数据结构复习的试金石。无论你是准备秋招春招、还在学C语言想检验水平还是工作几年想回头查漏补缺这套题都值得认真过一遍。1. 拿到这套题先看懂爱奇艺在考什么人很多同学刷题只盯着“题”忽略了卷子背后出题人的思路。笔试本质上是公司用最低成本筛选适合业务的人所以了解爱奇艺的C/C技术栈和岗位画像才能明白为什么考这些、不考那些。1.1 爱奇艺C方向岗位的业务背景爱奇艺的核心业务是视频平台C/C方向的岗位主要分布在几个层面播放器内核音视频解码、渲染、CDN和传输层优化、部分后端高性能服务、以及面向智能硬件的客户端组件。这些场景对语言的要求不是“会写”而是“写得好”——内存是否可控、性能是否经得起高并发和高流量冲击、代码是否具备工程可维护性这些都会直接体现在用户观看体验上。所以你会发现这套笔试题对C语言基础语法的考察并不多更侧重指针、内存、字符串这类“容易出错又必须掌握”的内容同时搭配数据结构与算法题。原因很简单视频平台的播放链路是高并发、高吞吐场景内存管理不当会引发崩溃和卡顿数据结构选型不对会影响延迟和带宽成本。笔试的每一个考点几乎都能在业务里找到对应场景。1.2 B卷的题型分布与答题节奏根据学弟的回忆这套B卷整体分两大块客观题和编程题。客观题以选择题为主覆盖C语言基础、指针、内存管理、数据结构和少量操作系统内容编程题有2到3道难度递进最后一题基本是算法设计题。我建议的答题节奏是客观题控制在30分钟内不会的题先标记跳过不要在单个题上死磕。编程题优先保第一题全对第二题尽量完整通过第三题即使写不出最优解也要给出暴力解法并写出思路注释。互联网笔试的评分标准不是“全对才给分”而是按用例通过率算的所以哪怕是部分正确的代码也能拿分。2. 核心考点逐项拆解为什么这些题最容易失分这套B卷的考点浓缩成一句话就是C语言功底 基础数据结构 算法思维。下面我逐个拆解并说明每个考点背后的原理和常见的失分原因。2.1 指针与内存管理C和C的第一道门槛指针在C语言里属于“会用不难用对很难”的知识点。这套卷子围绕指针的考查方式集中在以下几个方面指针的加减运算。int *p指向一块连续内存时p1到底偏移几个字节答案是sizeof(int)个字节不是1个字节。如果换成char *偏移量才是1字节。这个知识点在选择题里经常跟二维数组、函数传参组合在一起考比如int a[3][4]a、a[0]、a[0]、*(a1)这几个表达式的类型和值很多基础不牢的人一做就错。指针数组和数组指针。int *p[10]和int (*p)[10]看起来只差一个括号含义完全相反。前者是“10个int指针组成的数组”后者是“指向10个int数组的指针”。笔试时可以通过右左法则来快速判断先从变量名开始向右看遇到[说明是数组遇到)再向左看遇到*说明是指针。指针常量和常量指针。const char *p表示p指向的内容不能通过p修改char *const p表示p本身不能指向别处。这两个在C里还涉及与const_cast的纠缠笔试常考。注意很多同学笔试时栽在“指针常量”和“常量指针”的术语混淆上。记法很简单——看const靠近谁靠近类型表示“内容不可变”靠近变量名表示“指针本身不可变”。野指针和悬垂指针。这是内存管理的大头。一个指针在free之后没有被置空就成了悬垂指针一个指针没有初始化就使用就是野指针。B卷里应该有至少一道选择题专门考这个场景char *p (char *)malloc(100); free(p);之后再操作p会怎样答案是未定义行为可能崩溃也可能不崩溃但绝不能这么写。栈内存和堆内存。局部数组是在栈上分配的函数返回后栈内存就被回收了所以返回局部数组首地址是典型的错误写法。堆内存需要用malloc/calloc/realloc分配用free释放忘记释放就是内存泄漏。笔试对这种题很偏爱因为能同时考查变量的生命周期和对内存分区的理解。2.2 字符串与数组看似基础却最容易丢分字符串在C语言里就是字符数组加\0结尾但笔试中围绕它设计的陷阱非常多。sizeof 和 strlen 的区别。这是C方向笔试题的常青树。char str[] hello;中sizeof(str)是6包含\0strlen(str)是5。如果代码里写成for (int i 0; i strlen(str); i)循环会多执行一次访问到\0之后的位置。字符串逆序输出。这个题目看起来简单但手写代码时很多人会忘记处理空字符串、单个字符的边界情况或者在交换字符时用错了循环边界。后面我会专门写一节讲完整解法。缓冲区溢出。strcpy不检查目标缓冲区大小如果原字符串比目标数组长就会越界写入轻则数据被覆盖重则程序崩溃甚至被利用。笔试里考查strcpy/strncpy/memcpy的区别常考strncpy虽然限制了长度但不会自动补\0这也是个隐蔽的坑。数组作为函数参数时会退化为指针。void func(int arr[])和void func(int *arr)在C编译器中是等价的所以在函数内用sizeof(arr)拿到的是指针大小不是数组大小。这个知识点特别经典选择题里几乎必考一遍。2.3 数据结构基本功链表、栈、队列和排序数据结构部分B卷的重点集中在链表和排序上偶尔会带一道栈或队列的应用题。链表是C方向笔试的重头戏因为链表操作能同时考查指针操作、内存分配和边界条件处理。常见的出题形式有链表反转、链表中倒数第k个节点、判断链表是否有环、合并两个有序链表。排序算法里冒泡排序、快速排序、归并排序的手写是基本功。爱奇艺的笔试不太会直接让写一个完整排序而是以选择题形式考查各种排序的时间复杂度、空间复杂度和稳定性或者要求对某个给定序列进行一趟快排后的结果。实操心得我建议复习时把快排的递归写法、非递归写法、以及“单趟partition的三种实现方式”都过一遍。不是为了笔试手写而是为了应对面试时的思路提问——面试官会顺着你的代码不断追问比如“partition能不能用双指针优化”“最坏情况下时间复杂度是多少”这类延伸题。2.4 算法思维从递推到动态规划编程题的最后一题一般是算法设计题。常见方向包括动态规划最长公共子序列、最大连续子数组和、背包问题变种、贪心算法、或者DFS/BFS。为什么要考算法对视频平台来说推荐、调度、转码任务分配等场景都涉及算法优化。笔试题目的难度一般控制在LeetCode中等难度不会太偏但要求你有清晰的思路——哪怕写不出最优解也要能描述出暴力解和优化的方向。3. 编程题实操三道典型题目的完整解题路径编程题是笔试的拉分项。我挑了三个高频题型来完整演示不是光给代码而是把每一步的思考过程写出来这样你遇到变种题也能举一反三。3.1 字符串逆序输出从边界条件到完整写法要求输入一个字符串原地逆序后输出。拿到题先别急着写先想清楚几个问题字符串是否可能为空如果为空或长度为1直接返回不需要交换。逆序采用“首尾交换”法即i从0开始j从len-1开始i j时交换然后i、j--。是否允许使用额外空间题目说“原地”那就不能用新的字符数组。#include stdio.h #include string.h void reverse_string(char *s) { if (s NULL) return; int len strlen(s); if (len 2) return; int i 0, j len - 1; while (i j) { char tmp s[i]; s[i] s[j]; s[j] tmp; i; j--; } } int main() { char str[] hello world; printf(原字符串: %s\n, str); reverse_string(str); printf(逆序后: %s\n, str); return 0; }边界条件的处理是评分点如果写成for (int i 0, j len - 1; i j; i, j--)当i j时交换自己不影响结果但多了一次无意义的操作。更关键的是如果长度是奇数中间那个字符不需要交换如果用i j也不会有错只是不推荐。注意如果在笔试环境里字符串是以char *形式传入的要确认字符串存储区是可写的。如果传入的是字符串常量比如char *p hello;做逆序操作会引发未定义行为通常是段错误因为字符串常量存储在只读数据段。安全做法是用数组初始化char str[] hello;。这道题的延伸版本是不逆序整个字符串而是逆序每个单词。比如输入hello world输出olleh dlrow。思路是先整体逆序再按空格切分对每个单词逆序。这种变体在笔试中出现频率更高因为更能考查对数组边界的掌控力。3.2 链表反转循环与递归两种实现链表反转几乎是我见过频率最高的手写题。题目描述通常很简洁“反转一个单链表”。假设链表节点定义为struct ListNode { int val; struct ListNode *next; };循环法。循环法的核心思路是遍历过程中把当前节点的next指针翻转指向前一个节点。需要三个指针prev指向前一个节点curr指向当前节点next保存下一个节点防止断链。struct ListNode* reverseList(struct ListNode* head) { struct ListNode *prev NULL; struct ListNode *curr head; while (curr ! NULL) { struct ListNode *next curr-next; curr-next prev; prev curr; curr next; } return prev; }这里最容易犯的错是在curr-next prev之前没有先用next保存curr-next导致后面的节点丢失。很多笔试同学会说“思路会但一写就断链”就是这一步没想透。递归法。递归法的代码更短但理解门槛更高struct ListNode* reverseList(struct ListNode* head) { if (head NULL || head-next NULL) { return head; } struct ListNode *newHead reverseList(head-next); head-next-next head; head-next NULL; return newHead; }递归的关键在于先反转当前节点后面的链表然后让当前节点的下一个节点的next指向自己。这一步通常称为“穿针引线”。实操心得如果笔试时间充裕我建议写循环法因为递归法虽然代码短但对栈深度有要求——链表足够长时递归会爆栈。你可以在面试时提一句“递归版本存在递归深度风险工程上我倾向用迭代版本”这句话会加分。链表题的边界条件永远是空链表、只有一个节点、反转后头节点是否正确。这些都是测试用例爱考的点。3.3 最大连续子数组和从暴力到动态规划爱奇艺这套题里有一道编程题很像LeetCode第53题“最大子数组和”。题目是让求一个整数数组中和最大的连续子数组的和。暴力解作为保底。双重循环枚举所有起点和终点累加求和。时间复杂度 O(n²)空间复杂度 O(1)。笔试时如果实在想不出最优解写暴力解也能过一部分测试用例。int maxSubArray(int* nums, int numsSize) { int maxSum nums[0]; for (int i 0; i numsSize; i) { int sum 0; for (int j i; j numsSize; j) { sum nums[j]; if (sum maxSum) { maxSum sum; } } } return maxSum; }动态规划优化。DP思路很直观以dp[i]表示以第i个元素结尾的最大子数组和。对于dp[i]要么单独成为子数组要么和前面的子数组合并。状态转移方程是dp[i] max(nums[i], dp[i-1] nums[i])最终答案是所有dp[i]中的最大值。由于dp[i]只依赖dp[i-1]可以用一个变量滚动更新不需要开数组。int maxSubArray(int* nums, int numsSize) { int curSum nums[0]; int maxSum nums[0]; for (int i 1; i numsSize; i) { if (curSum 0) { curSum nums[i]; } else { curSum nums[i]; } if (curSum maxSum) { maxSum curSum; } } return maxSum; }这里的if (curSum 0)等价于max(nums[i], curSum nums[i])因为如果前面的累计和是负数加上反而拖累不如从当前元素重新开始。实操心得笔试时建议先写出暴力解再在注释里补一句“可以用DP优化到O(n)”然后再写DP版本。这样做的好处是告诉阅卷人你有完整的优化意识。另外如果数组中包含负数不要模拟样例时出错——最经典的坑是nums {-1, -2, -3}时最大值应该是-1但不是0因为题目要求子数组不能为空。4. 笔试中的常见问题与排查技巧实录这一节我把刷题和实际笔试中遇到的典型问题汇总一下按“编译前、运行时、测试后”三个维度来整理方便你快速对照。4.1 编译和链接期的常见报错找不到头文件 / 未声明的标识符。笔试环境通常不会自动给你补全头文件。用strlen要写#include string.h用malloc要写#include stdlib.h。很多同学手写代码没问题一上机就漏头文件导致编译失败很冤。函数声明顺序错误。如果main函数在前面自定义函数在后面C语言要求在使用前声明函数。可以在文件开头加一个函数原型声明或者把自定义函数写在main之前。笔试时最好统一在开头声明避免来回调整。分号和括号不匹配。这个看起来低级但紧张时特别容易犯。建议写完代码先花30秒通读一遍或者靠编译器的报错行号定位。在IDE里可以第一时间看到红线但在笔试网页编辑器里只有提交后才知道编译结果。4.2 运行时的典型踩坑段错误Segmentation Fault的常见原因。我在笔试辅导中见到的段错误九成来自三种情况访问空指针比如head NULL时直接head-val、数组越界循环边界写错、修改了字符串常量给char *p abc赋值。排查思路先在代码里查所有指针操作之前是否有判空再查所有数组下标是否可能越界最后看是否有对只读内存的写操作。死循环的常见原因。链表遍历时没有更新当前节点指针或者while条件写成了永真式。遇到死循环先按CtrlC终止然后检查循环体内是否每个分支都能让循环变量向终止条件靠近。输入输出的坑。线上笔试网站通常要求处理多组输入比如“输入包含多组测试数据每组第一行是n”要用while (scanf(%d, n) ! EOF)的模式。如果题目没写多组数据但样例输出有多个基本就是多组输入。另外输出格式的换行空格也要严格对齐常见的错是“每个结果后多打一个空格”或“最后一行多打一个换行”。4.3 常考选择题易错点速查为了方便复习我把这套B卷里最常出现的易错点整理成表格考点类型典型题目描述易错点正确思路指针加减int a[5]; int *p a; p1 指向?错以为加1字节加一个sizeof(int)sizeof/strlenchar *p abc; sizeof(p)错以为等于4或3指针的字节数32位是464位是8指针常量/常量指针const char *p能否修改p[0]混淆“指针可变”和“内容可变”const修饰char内容不可变内存泄漏malloc后未free会怎样以为立即崩溃不会立即崩溃但内存持续增长局部变量返回函数返回局部数组名以为可以用栈内存已回收属于悬垂指针二维数组a[i][j]与*(*(ai)j)等价不熟悉指针形式二者等价笔试常见变形快排复杂度快排平均/最坏时间复杂度只说O(n log n)平均O(n log n)最坏O(n²)4.4 笔试环境使用技巧爱奇艺这类公司一般用第三方在线笔试平台代码编辑器和本地IDE差别较大。建议提前做两件事第一去牛客网或赛码网熟悉在线笔试的代码编辑环境。很多平台不会自动补齐括号、不会提示编译错误代码要一次性写完这需要平时练习手写代码的能力。平时刷题建议关掉IDE的自动补全直接在网页编辑器里写。第二编程题提交后如果显示“只通过部分用例”不要慌。先根据报错信息怀疑两个方向边界条件空输入、最小值、最大值、单元素和数据类型int溢出要用long long时用了int。比如数组元素求和超过int上限结果就错了。5. 笔试之外的延伸从刷题到面试的准备路线笔试不是终点笔试通过后的面试通常会针对你写的代码进行延伸提问。因此刷完这套B卷之后我建议沿着下面几个方向继续深挖让复习效果最大化。5.1 从笔试考点到面试追问面试官看到你笔试题里写了malloc/free会追问malloc和new的区别C方向或者malloc底层如何实现操作系统方向。看到你用了递归会追问递归和迭代的取舍以及栈溢出的风险。我建议这样准备每刷完一道题不要只满足于“通过”而是自己给自己出三个延伸问题。比如做完链表反转问自己如果链表是双向链表怎么办如果只允许 O(1) 额外空间怎么办如果有环怎么办这些问题回答不出来就回去看书不放过任何一个模糊点。5.2 C/C岗位复习的资料与节奏如果你是基础比较薄弱的学生我建议按这个顺序复习C语言语法与指针把指针、数组、字符串、结构体、内存管理等基础知识过一遍推荐KR的《C程序设计语言》和《C和指针》。数据结构重点复习链表、栈、队列、二叉树、哈希表。每种结构都要能手写基本操作并且能说出适用场景。算法排序、二分查找、双指针、滑动窗口、递归、动态规划。这个阶段可以配合LeetCode刷题按专题刷不要随机刷。操作系统与网络进程线程、内存管理、TCP/UDP、HTTP。笔试选择题会考面试也会延伸到。C高频特性如果投递的是C岗位还要掌握虚函数、智能指针、STL容器底层原理、移动语义等。复习节奏上我建议把时间分成三块基础巩固约40%、刷题练习约40%、总结复盘约20%。不要光看题解不动手手写代码的肌肉记忆只有真的写了才有。5.3 这套题对非笔试场景的价值即使你现在不找工作我也推荐把这类经典笔试题做一遍。原因很简单C语言的知识点呈网状笔试题目恰好是检验网状结构完整度的手段。你做错了某道题不只是这道题不会而是背后的那一片知识有漏洞。比如你被“指针数组和数组指针”这道题难住了说明你对“声明语法优先级”的理解不牢这在阅读复杂第三方C代码时一定会踩坑。你被“字符串逆序”难住说明对数组边界的敏感度不够这在处理网络协议解析、二进制数据转换时同样重要。所以把这些笔试题当成体检报告哪项指标弱就补哪里这种复习方式比盲目刷题高效得多。我自己的习惯是每次做完一套笔试题都把错题整理进一个文档标注“知识点、错误原因、正确思路、相关延伸题”。过两周再重新做一遍看是否还会犯同样的错。这个过程看着笨但对巩固基础特别管用。这套爱奇艺2019秋招C方向笔试题B整体设计得很扎实客观题考基础积累编程题考临场思维和代码功底不存在碰运气能过的可能。建议你认真做过一遍之后把错题回归到对应知识点上再把典型题目能默写出来的程度——到时候无论是笔试还是面试心里都会踏实很多。如果你在做题过程中遇到了具体某道题卡住欢迎带着题面来聊我可以单独拆一篇解题思路。