
1. 金融IT研发笔试的“底味”先看懂这家公司和这份卷子的定位1.1 恒生电子的业务底色为什么数学、金融常识会成为隐藏考点把“恒生公司2016研发工程师笔试卷”这个标题扔到搜索引擎里你能翻到不少论坛帖子和网盘文档但大多数人只是存了题刷了一遍就不了了之。我想从另一个角度聊这份卷子先看看出题的公司到底在做什么再回来看题你会发现很多看似无关的考点其实都有业务逻辑在后面。恒生是金融IT领域的头部玩家核心业务覆盖证券、基金、银行、保险、交易所等金融机构的核心交易系统、风险控制系统、清算系统。这类系统的共同特点是高并发、高可用、强一致、低延迟而且绝对不能出账目错误。交易撮合、行情推送、订单处理每一笔都要经得起审计资金数字错了不是“修个bug”那么简单是直接的经济损失和监管问题。这决定了公司招研发工程师的时候筛人重点和互联网公司不完全一样。互联网公司可能更看重算法、高并发架构、业务快速迭代能力而金融IT公司除了看重计算机基础还非常在意你对内存、并发、事务、数据一致性的理解是否深入。因为交易系统里密集使用C/C或Java底层直接操作内存、网络、数据库任何一点基础不牢都可能酿成线上事故。所以这份笔试卷虽然标着2016年但它背后的命题思路一直延续到今天基础扎实度优先工程严谨性优先业务理解能力优先。看懂了这一点再刷题才有方向而不是盲目追求“难题偏题”。1.2 2016年的笔试卷放在今天为什么还有复盘价值有人可能觉得2016年的笔试卷都过了这么多年技术栈早变了刷它还有什么意义我的看法恰恰相反。金融IT行业的核心技术栈其实非常稳定C/Java、Linux、Oracle/MySQL、中间件、内存缓存、网络通信这些核心基础设施在十年间没有发生颠覆性变化。尤其是交易系统讲究的是稳定可靠不会像互联网前端一样一年换一个框架。这份试卷的价值在于三点第一它完整呈现了金融IT研发岗的考察框架。计算机基础四门课——数据结构、操作系统、计算机网络、数据库——加上一门编程语言C/C或Java再加少量逻辑题和行业常识题基本就是这类笔试题的标配。今天很多金融科技公司的笔试题也跳不出这个框架。第二它代表了一种“老派但有效”的筛选风格。不考现场造火箭不考冷门API考的是你大学四年到底有没有把基础课学明白。指针怎么用、链表怎么遍历、SQL的join结果是什么、进程和线程有什么区别。这些东西到工作中都是天天要用的笔试考它们是在模拟一个基本的上岗门槛。第三对比今天的笔试2016年的卷子还透露了一个趋势变化现在的题目更强调工程化和场景化会给你一个交易场景让你设计接口、排查故障而当年的题目更偏向基础知识点的记忆和计算。两相对照你就能看出哪些是永恒不变的硬功夫哪些是需要额外补的软实力。把这套老卷刷透再去看新的笔试题会有一种“降维理解”的轻松感。1.3 整体卷面结构与我观察到的命题风格我对着网上流传的多个版本梳理了一下这套卷子的结构大致可以归纳为选择题约40%-50%、简答题约20%-30%、编程题约20%-30%部分版本还会有逻辑推理题。题量不算特别大但覆盖范围广要求在限定时间内答完对知识面的广度要求高于单题难度。从命题风格来看有几个明显特征选择填空偏基础会直接考sizeof的计算、指针自增的运算优先级、数组越界的后果、二叉树遍历顺序、排序算法的复杂度比较。这些题本身不难但陷阱很多一个不仔细就容易错。简答考原理比如“死锁的四个必要条件”“TCP三次握手过程”“进程和线程的区别”“事务的ACID特性”。要求你写清楚、写完整不能只答关键词。编程题考实现能力链表操作、字符串处理、排序查找是三大常客。不要求一定用某个语言但C/C或Java至少得熟练到能直接写。行业题看视野偶尔会出现“基金净值怎么算”“证券交易的基本流程”“什么是撮合交易”之类的问题考察的是你对金融业务有没有基本认知。这套卷子的整体难度我认为属于“中等偏上”但它的中等不是建立在题目刁钻上而是建立在覆盖面上。你大学基础课但凡有一门学得糊里糊涂很容易在这里暴露出来。所以复盘这张卷子本质上是在给自己做一次计算机基础的大体检。2. 从真题类型反推六类高频考点的考查逻辑与准备重点2.1 C语言基础与内存管理指针、数组、结构体的“连环陷阱”C语言在金融IT领域至今仍是后端核心系统的常用语言所以C语言基础几乎是这套卷子的必考板块。考查点集中在指针运算、内存布局、结构体对齐、数组与指针的关系、字符串处理这几个方向。先说指针和数组。有一类经典题目会这样出char *p hello; char arr[] hello; printf(%zu %zu\n, sizeof(p), sizeof(arr));问输出的结果。答案是在64位系统上p是char*类型占8字节而arr是数组sizeof(arr)返回整个数组的大小hello共6个字符含字符串结束符\0所以输出8 6。这道题看似简单但能同时考出三个知识点指针的大小取决于平台位数、数组名不是指针、字符串常量在C中默认带尾零。结构体对齐也是一道高频题。结构体里的成员顺序不同整个结构体的大小会不一样。比如struct A { char c; int i; }; struct B { int i; char c; };在32位平台上sizeof(struct A)是8char占1字节填充3字节int占4字节sizeof(struct B)也是8。但如果再加一个char成员顺序不同会导致不同的对齐填充。这类题考验的是对内存布局的理解而不只是死记公式。我当时复习这类题的经验是不要满足于算出答案而是亲手写一段程序跑一遍再用offsetof和地址打印验证每个成员的真实偏移量。这样一遍下来对齐规则就刻在脑子里了。另外字符串相关的strcpy、strcmp、strlen的返回值、边界行为也是常客。建议刷题时把C语言运算符优先级表放在手边*p和(*p)这类表达式的求值顺序是很多人丢分的重灾区。2.2 数据结构与算法链栈队列排序查找的“性价比之王”数据结构在笔试中的占比通常最高。2016年这套卷子涉及的题型放到今天依然不过时单链表反转、判断链表是否有环、栈和队列的相互实现、二叉树的先中后序遍历、排序算法的稳定性与复杂度、二分查找的边界处理。我在复盘时有个很深的感受**笔试考的数据结构题目往往不是要你写一个高深的算法而是考最基本的操作的边界处理是否滴水不漏。**比如说单链表反转看起来十几行代码就能写完但新手常见的错误包括没有保留下一个节点的指针就直接改了当前节点的next导致链表断掉没有处理空链表和单节点链表的特殊情况循环结束后没有把头指针指向新的头节点。针对这类题我建议你用“先画图再写码最后跑用例”的三步法。画图能帮你把指针变换的每一步都看清楚写完代码后至少跑三个用例空链表、单节点、普通长度链表。这样才能保证代码在笔试环境下零失误。二分查找也是容易踩坑的点。很多人能写出循环版但mid (low high) / 2在low high较大时可能整数溢出正确写法是mid low (high - low) / 2。还有边界问题查找区间是左闭右闭还是左闭右开退出条件到底是low high还是low high必须同一套逻辑保持一致否则就会在边界元素上出错。排序算法部分面试官常考快速排序的partition过程、归并排序的稳定性、堆排序的建堆和调整流程。不要只背复杂度表要能手写至少两种排序并能解释每一轮操作后数组的状态变化。很多简答题会让你写出“第二趟快速排序后的序列”这种题只能靠手动模拟来练熟。2.3 操作系统与计算机网络同步、死锁、TCP/IP的必问组合操作系统和计算机网络常常放在同一板块。操作系统重点考进程与线程的区别、进程间通信方式、死锁的四个必要条件、页表与虚拟内存、信号量机制网络重点考TCP三次握手与四次挥手、TCP与UDP的区别、IP地址规划、HTTP协议状态码。死锁是出现频率最高的考点之一因为它既有理论性又有工程性。考题形式经常是给一段并发代码问是否会产生死锁并说明如何避免。要答好这类题必须熟练背诵并真正理解死锁的四个必要条件——互斥、持有并等待、不可剥夺、循环等待——然后从每个条件出发去讲对应的破坏方法用读写锁或原子操作打破互斥、用一次性申请所有资源打破持有并等待、用超时机制打破不可剥夺、用资源有序分配打破循环等待。TCP三次握手也是必考题而且考法越来越细。不只是让你描述交互过程还会问“为什么需要三次握手”“SYN Flood是什么”“第二次握手丢失会发生什么”。有一次我帮人看这套卷子的参考答案发现有人把三次握手和HTTP的连接过程混在一起写逻辑完全乱了。复习的时候要把“TCP传输控制协议的三次握手建立连接”和“HTTP协议基于TCP完成一次请求响应”这两件事分开别混淆层次。操作系统的进程线程题不要只答“进程是资源分配的最小单位线程是CPU调度的最小单位”最好再补充一句“同一进程内的线程共享地址空间和文件描述符但各有独立的栈和寄存器上下文”。如果能结合金融系统的实际场景——比如交易网关里用多线程处理不同客户的请求而用多进程隔离不同的业务模块——会显得更有说服力。2.4 数据库与SQL多表查询、事务、索引的实战取向数据库是金融IT笔试的重头戏因为交易系统的核心就是数据。这套卷子的数据库题几乎绕不开三块SQL多表查询、事务的ACID和隔离级别、索引的原理与使用。SQL多表查询最喜欢考的是INNER JOIN、LEFT JOIN、RIGHT JOIN的区别以及GROUP BY配合聚合函数的使用。有一类经典考题是“有两个表员工表和部门表统计每个部门的员工数列出部门名称和人数没有员工的部门也要显示。”这题的考点就在于必须用LEFT JOIN而不是INNER JOIN否则没有员工的部门就会被过滤掉。如果你在写的时候忘记在GROUP BY后加HAVING做条件过滤也会漏掉一部分业务逻辑。索引部分笔试常考的是B树索引和哈希索引的区别、联合索引的最左前缀原则、什么时候索引会失效。比如“对建了联合索引(a, b, c)的表执行WHERE b1 AND a2能不能用到索引”“对列做了函数运算后还能不能走索引”。这类题需要通过实际执行计划来验证别凭感觉猜。我建议在本地装个MySQL用EXPLAIN命令看执行计划把几种常见情况全部跑一遍印象会非常深。事务的ACID几乎是送分题但隔离级别是分水岭。读未提交、读已提交、可重复读、串行化这四档隔离级别分别解决脏读、不可重复读、幻读中的哪些问题一定要能用一句人话说清楚。金融系统对强一致有天然要求所以如果能在简答题里结合“资金转账”的例子来讲事务比如“A账户扣款和B账户入账必须在同一个事务中任一失败则全部回滚”会大大加分。2.5 面向对象与Java基础金融系统对封装、多态的偏好如果试卷出现了Java题通常围绕面向对象三大特性、集合框架、异常处理、JVM基础展开。恒生这类金融IT公司早期大量使用Java开发应用系统所以面向对象设计能力是考察重点。面向对象部分常考重载和重写的区别、接口和抽象类的选择、String、StringBuilder、StringBuffer的区别、HashMap的底层原理。其中HashMap是重中之重常考的点包括put流程、扩容机制、为什么线程不安全、1.7和1.8头插尾插的区别。很多人能背出入参和返回值但要解释“为什么链表长度超过8才转红黑树”就需要一点概率论和工程权衡的知识了。封装、继承、多态这三大特性笔试更爱用“写出以下程序的输出结果”来考。这种题最见基本功比如子类继承父类后静态方法能否被重写、private方法能否被重写、多态方法调用的绑定机制。建议复习时把“静态绑定”和“动态绑定”这两个概念理清楚笔试时就不容易慌。2.6 逻辑推理与行业常识题兼顾脑力和业务视野最后这部分虽然占分比不高但在面试官眼里却是区分度很大的题。逻辑推理题通常是数字推理、图形推理、真假话判断考场策略是放在最后做别让它们占用前面基础题的时间。行业常识题则需要平时积累比如金融系统的核心模块怎么划分、一套基金交易系统大致包含哪些环节、什么是合法合规的数字签名和数据加密需求。这类题没有标准复习书多看看金融IT行业的技术白皮书、产品介绍哪怕是在官网浏览几个解决方案文档都会心中有数。3. 挑几道代表性题目做“解剖”解题思路与失分点复盘3.1 指针题Modify函数的输出到底是多少C语言指针是笔试钉子户我见过一道被引用次数最多的题大概长这样void Modify(int *p) { p; } int main() { int a[2] {10, 20}; int *p a; Modify(p); printf(%d\n, *p); return 0; }考的是输出是10还是20答案是10。因为C语言函数参数是值传递Modify(p)把指针变量p的值拷贝了一份传进函数函数内部p只修改了形参的指向不会影响实参p。这个知识点看似简单但几乎年年有人错。如果把题目改成void Modify(int *p) { (*p); }那输出就会变成11因为*p解引用后修改的是数组第一个元素的值。这两个版本放在一起对比就能把“传值不传引用”“修改指针本身”和“修改指针指向的内容”彻底区分开。排查这类题的失分点主要看三点第一是否清楚形参和实参的关系第二是否区分p、*p、p三个表达式的含义第三是否知道数组名在表达式里会退化为指向首元素的指针。建议用手写内存图的方式做题栈上画一片内存标出每个变量的地址和值把所有赋值过程走一遍答案自然就出来了。3.2 链表和树的操作题递归与迭代的边界细节编程题部分链表的创建和遍历属于“热身题”真正拉分的是对边界条件的处理。举个例子反转单链表很多人用迭代法能写对但代码显得很不“干净”对空链表和单节点链表没有单独处理我在批改风格上能明显看出哪些人基础扎实、哪些人只是背过答案。链表反转的迭代写法要养成固定习惯struct ListNode* reverseList(struct ListNode* head) { struct ListNode *prev NULL, *curr head; while (curr) { struct ListNode *next curr-next; curr-next prev; prev curr; curr next; } return prev; }写的时候脑子里要一直想着那三根指针prev指向已反转部分的新头curr指向当前待处理的节点next保存即将断开的后续节点。为什么需要next因为一旦执行curr-next prev原链表后面的节点就找不到了必须提前保存。这个理由在面试现场说出来非常加分。树遍历的题则常考“手写先序遍历并输出节点值序列”。很多人会递归写法但非递归写法写不完整。非递归先序遍历要借助栈顺序是“先压右子树再压左子树”这样弹栈时才先访问左子树。如果这一点在笔试时没想清楚代码就会出现访问顺序错误。我的建议是树的题统一掌握递归和非递归两种写法因为很多公司的笔试环境会考察栈深度和代码鲁棒性。3.3 SQL查询题从“两个表的连接”到“部门统计”数据库题里有一道高频SQL我把它改编出来给大家参考员工表CREATE TABLE emp ( emp_id INT PRIMARY KEY, emp_name VARCHAR(50), dept_id INT, salary DECIMAL(10,2) );部门表CREATE TABLE dept ( dept_id INT PRIMARY KEY, dept_name VARCHAR(50) );题目要求查询每个部门的部门编号、部门名称和员工人数没有员工的部门也要列出结果按部门编号升序排列。标准答案SELECT d.dept_id, d.dept_name, COUNT(e.emp_id) AS emp_cnt FROM dept d LEFT JOIN emp e ON d.dept_id e.dept_id GROUP BY d.dept_id, d.dept_name ORDER BY d.dept_id;这里最关键的坑是员工人数要用COUNT(e.emp_id)而不是COUNT(*)。如果用COUNT(*)在LEFT JOIN产生的那些“员工为NULL”的行也会被计成1导致没有员工的部门显示人数为1这可是经典错误。另外ORDER BY要按部门编号排很多人写成了ORDER BY emp_cnt和题目要求不一致属于审题失误。如果题目再升级一档会要求“找出平均工资高于公司平均工资的部门”这就要用到子查询或HAVING。先算出公司的平均工资再用GROUP BY dept_id按部门分组最后用HAVING AVG(salary) (SELECT AVG(salary) FROM emp)过滤。SQL题讲究的是把业务逻辑翻译成代码的准确性所以在考场里先想清表连接关系再动笔比一上来就敲SQL高效得多。3.4 并发与死锁题为什么“互斥持有并等待”一定会出问题并发类简答题经常给一个经典场景两个线程分别持有资源A和资源B同时还想申请对方手里的资源然后问会不会死锁怎么避免。这类题的标准答案分三步第一步判断是否满足死锁的四个必要条件互斥条件A和B同一时刻只能被一个线程占用、持有并等待条件每个线程持有自己的资源同时等待对方的资源、不可剥夺条件线程不能强行拿走对方持有的资源、循环等待条件线程1等线程2的资源线程2等线程1的资源。四个条件同时满足必然死锁。第二步指出可以打破哪一条件。最简单的是打破循环等待让所有线程按固定顺序申请资源规定必须先申请A再申请B就不会出现“你等我的B我等你的A”的循环。第三步补充工程上常用的手段用锁的超时机制避免无限等待比如Java里tryLock指定等待时间或者用读写锁、并发集合、原子类来减少不加控制的多线程资源竞争。我在复盘这类题时发现很多人能背出四个条件却不会结合代码场景分析。建议平时练习时随便写一段多线程代码然后强制自己指出四个条件分别对应代码里的哪一行、哪个变量坚持几次以后这类型的题基本就是送分。4. 这套卷子怎么刷才有效备考路径、时间分配与应试技巧4.1 阶段安排基础巩固、专项刷题、模拟计时三步走如果你决定认真刷这套2016年的卷子我建议分三个阶段推进别一上来就整套整套地做。第一阶段基础巩固用时3-5天。把数据结构、操作系统、计算机网络、数据库这四门课的核心教材目录过一遍挑出和这套卷子考点重合的章节重点看。C语言重点复习指针、结构体、内存管理Java重点复习集合和JVM基础网络重点整理TCP/IP协议栈数据库重点看索引和事务。这一步的目标不是刷题而是把知识体系的骨架搭起来。第二阶段专项刷题用时5-7天。按题型分类集中刷。第一天专门做C语言和数据结构题第二天专做操作系统和网络题第三天专做数据库和SQL题第四天做编程题并限时。每做完一道题不要急着看答案先标记出自己的犹豫点结合参考答案逐行分析把错误原因归成三类知识点空白、审题失误、计算粗心。归类的过程比做题本身更能暴露薄弱环节。第三阶段模拟计时用时2-3天。用完整时间段模拟真实的笔试环境。设好90分钟倒计时中间不查资料、不中断做完后严格评分。模拟的主要目的不是看分数而是训练时间分配感。我的经验是选择题和填空题控制在25分钟内简答题控制在30分钟内编程题至少留出25分钟最后10分钟检查答题卡。4.2 错题本与“题眼”归纳让一套卷子顶十套卷子刷题不在于量多而在于有没有把每一道题背后的“题眼”找出来。所谓题眼就是命题人真正想测试的那个知识点。比如一道看似复杂的链表题题眼可能是“是否需要dummy node来简化头节点处理”一道看似简单的SQL题题眼可能是“LEFT JOIN和COUNT字段的选择”。我建议把错题按“题眼”归类记录而不是按题目归属的章节记录。比如设立几个栏目指针语义混淆、数组越界判断、死锁条件分析、SQL连接方式选错、索引失效场景、并发边界问题。每次跳进同一个坑就在对应的栏目标记一次。别小看这个动作它能让你在考前用20分钟快速过一遍所有薄弱点而不是茫然地从头翻错题本。我自己当年刷题时还习惯在每道错题旁边写“命题人想考我什么”写不出来就说明理解不到位。这个习惯对应对简答题特别有效因为简答题的给分点往往就是题眼所在答中题眼就有分答偏了写再多也没用。4.3 应试细节从时间分配到“先易后难”的实战技巧考场上有几个细节最容易拉分值得专门提出来。第一遇到两分钟还没有思路的题先标记跳过。笔试的时间成本很高一道选择题卡住5分钟可能就少做一道送分题。把会做的全部拿到手再回来啃硬骨头是性价比最高的策略。第二编程题先写解题思路再写代码。哪怕最后的代码有bug思路清楚也能让阅卷人理解你的意图。有些题目可能是人工评审解题步骤和注释可以成为隐含的得分点。第三SQL题先写FROM和JOIN再写WHERE和SELECT最后写GROUP BY和ORDER BY。这个顺序能保证你不会漏掉连接条件还能在写复杂查询时保持逻辑清晰。第四注意审题时的单位、边界和隐藏条件。比如“数组长度不超过1000”意味着你可以用O(n^2)算法“排序输出后要求去重”意味着不能只排序完事题目说“用递归实现”你就别写迭代。这些字眼都是命题人刻意埋的信息审题不是看一遍而是圈出关键词。5. 写在最后金融IT岗位笔试的底层逻辑与个人体会复盘这份2016年的恒生研发笔试卷我最深的体会是**这类试卷考的不是智商而是“大学四年有没有认真把基础学扎实”。**指针、链表、死锁、事务、TCP三次握手这些考点没有一项是冷门偏门全是计算机专业课程里的主干内容。可每年依然有一大批人在这些基础题上翻车原因不是题难而是学的时候浮于表面做题时靠记忆而非理解。如果你现在还在面试和笔试阶段我的建议是把这份卷子当成“体检单”别太在意分数。它最宝贵的价值是帮你在短时间内检视出知识体系里的空洞。哪个板块扣分多哪个知识点让你犹豫超过两分钟那就是你接下来一周的复习重点。如果你已经工作再看这份卷子反而会多一层理解原来当年那些“背了也不知道有什么用”的考点在真实交易系统里一个都躲不掉。内存管理关系到交易队列的稳定死锁分析关系到多线程撮合的正确性数据库事务关系到资金账目的零差错。基础之所以叫基础不是因为简单而是因为所有的复杂都是建在它之上的。最后分享一个我做这套题时的小方法不要直接在卷子上写答案准备一张A4纸把每道题涉及的知识点在纸上用一句话写出来做完全卷后把这页纸贴起来当目录。日后复习时你会发现这些一句话目录比任何笔记都好用因为它逼着你把飘在脑子里的知识落到纸面上。刷题不是目的把知识内化成自己的判断力才是笔试之后真正让你走得更远的东西。