恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
春招编程笔试复盘:OTA平台算法题、Java并发与笔试避坑指南
首页
资讯中心
/
春招编程笔试复盘:OTA平台算法题、Java并发与笔试避坑指南
春招编程笔试复盘:OTA平台算法题、Java并发与笔试避坑指南
发布时间:2026/9/1 14:16:12
2023年春招投去哪儿的时候我没想到编程笔试会刷掉那么多人。当时我报的是后端研发岗线上笔试一共90分钟前面20道选择题后面4道编程题全程在一个不支持本地IDE、只能在线提交的网页编辑器里完成。考完之后我复盘了很久发现这类在线旅游平台的编程笔试和一般互联网大厂有些区别不是单纯把LeetCode刷完就能拿下的。这篇文章想把当时的题型、解题思路、踩坑点都整理出来给后面准备春招、秋招的同学做个参考里面有些细节和教训是我实际考试之后才真正想明白的。1. 一次春招编程笔试到底在考什么1.1 去哪儿笔试的整体印象与考察定位2023年春招是恢复线下实习和校园招聘节奏比较明显的一年去哪儿作为在线旅游平台技术岗笔试延续了“选择题编程题”的混合模式。我记得笔试开始前系统会先让你签一份在线诚信承诺然后自动打开摄像头监控网页不能随意切换、不能复制粘贴。这意味着你平时熟悉的本地IDE自动补全、代码片段直接拖拽这些操作在考场上全部失效所以准备阶段一定要养成手写代码和直接在网页编辑器里敲代码的习惯。从题目构成来看选择题覆盖了数据结构、操作系统、网络、数据库和Java/Python语言基础编程题则集中在数组、字符串、动态规划、贪心和模拟这几类。去哪儿这类业务型公司很少出特别偏门、特别竞赛向的题更多是让你在限定时间内用代码解决一个业务里可能出现的实际问题。换句话说它考的不是你会不会炫技而是你能不能稳定、清晰地把一个需求写成能跑的代码。我印象比较深的还有一点整个笔试界面会实时显示剩余时间而且编程题的通过率是按测试用例算的不是只看最终有没有跑通。所以哪怕你不能AC所有用例只要把暴力解或者部分正确的写法提交上去也能拿到一部分分数。这个规则很关键直接决定了我后面做题时的策略选择。1.2 选择题里容易被忽视的知识点选择题是我翻车比较严重的地方因为平时刷题只盯着算法到考场上才发现很多计算机基础已经忘得差不多。这里多说一句准备春招笔试时不要把“编程”窄化成“算法”基础知识的优先级一样高甚至更高。我印象比较深的一道选择题是关于数据库索引的。题目给了一张订单表字段有用户ID、订单状态、下单时间问下面哪个SQL语句能用上联合索引。去哪儿这类OTA平台订单查询是最核心的业务场景这个题几乎年年出现。答案的核心是“最左前缀原则”也就是联合索引里字段的顺序要和查询条件从左到右匹配。如果你只建了(user_id, status, order_time)的联合索引那么where里只写status或只写order_time都用不上这个索引。操作系统和网络的选择题也占了不少比例。比如进程和线程的区别、死锁产生的四个必要条件、TCP三次握手和四次挥手的流程、HTTP和HTTPS的端口号差异。这些内容不需要你背得一字不差但要在60秒内判断出哪个选项是对的。我当时就是因为在网络上花的时间多了最后几道选择是蒙的所以建议大家笔试前专门抽一两天把计算机网络和操作系统的常见考点快速过一遍别把复习时间全押在算法题上。2. 编程题题型拆解与思路复盘2.1 OTA场景下的算法题字符串处理和模拟编程题里最让我有“去哪儿味”的一道是把一个带时区的字符串时间转换成另一个时区的对应时间。题目给的是类似“2023-03-15 14:30:00 UTC8”这样的输入要你输出纽约时间的对应格式。这类题的本质是字符串解析加日期计算LeetCode上找不到一模一样的原题但和“Valid Number”“字符串转整数”是同一个套路。拿到这种题第一步不是急着写代码而是先把输入格式拆清楚。比如时区偏移可能带半小时甚至四十五分钟像印度时区就是UTC5:30如果你只处理了整小时偏移后面用例就会挂。我当时的思路是先用分隔符把年月日时分秒拆出来再单独提取时区偏移量统一换算成UTC时间戳最后再按目标时区偏移量输出。用时间戳作为中间格式能避免跨月、跨年时手动进位出错。下面是一段面向笔试的简化版Java示意代码核心思路就是用UTC秒数做中转import java.time.LocalDateTime; import java.time.ZoneOffset; public class TimeConverter { public static void main(String[] args) { // 模拟输入2023-03-15 14:30:00 UTC8 - UTC-5 String datetime 2023-03-15 14:30:00; int srcOffset 8; // 源时区UTC8 int targetOffset -5; // 目标时区UTC-5 LocalDateTime ldt LocalDateTime.parse(datetime.replace( , T)); long utcSeconds ldt.toEpochSecond(ZoneOffset.UTC) - srcOffset * 3600L; LocalDateTime targetTime LocalDateTime.ofEpochSecond( utcSeconds targetOffset * 3600L, 0, ZoneOffset.UTC); System.out.println(targetTime); } }这段代码在笔试里属于“能过大部分用例但缺少边界校验”的版本。真要追求满分还得处理输入里可能出现的非法时间、时区偏移大小为负号、以及秒数为闰秒等情况。不过在90分钟的笔试里先把主干逻辑跑通比一上来就堆异常处理要划算得多。2.2 数据结构题为什么优先用数组而不是集合第二道编程题是一个数组题题目大致是给一个整数数组找出连续子数组的最大和。这道题本质是经典的Kadane算法最优解能做到O(n)时间、O(1)空间LeetCode上有个原题叫“Maximum Subarray”。很多人一看是简单题就会放松警惕但它的考点其实藏在空间复杂度里。正确写法是维护两个变量一个记录当前累加和cur一个记录历史最大值max。每遍历一个数cur max(cur num, num)max max(max, cur)。代码非常短public int maxSubArray(int[] nums) { int cur 0; int max Integer.MIN_VALUE; for (int num : nums) { cur Math.max(cur num, num); max Math.max(max, cur); } return max; }有的候选人第一反应是先用前缀和数组再枚举所有子区间这样也能做对但数组长度一旦到10^5以上就会超时。我之所以把这个题拎出来说是因为它考察的不只是“你会不会写”而是“你能不能想到用常量空间”。核心直觉是如果当前累加和已经是负数那它对后续加和只会有负面贡献干脆从当前元素重新开始。这个思想和业务里的止损逻辑很像理解透了代码就不会忘。另外这套题里还出现过用ArrayList还是int[]的对比选择。性能敏感场景下数组能节省装箱、扩容开销笔试系统有时会用大数据量卡超时所以能用原始数组就别用包装类集合能用HashMap就别用ArrayList做查找。这个习惯在笔试和实际工作中都有价值。2.3 并发和异步编程题2023年绕不开的热门考点这两年笔试和面试里并发和异步编程的出现频率明显上升。去哪儿2023春招的选择题里虽然没有直接让写多线程代码但出现了CompletableFuture异常处理的选项这让我意识到只会写单线程算法已经不太够用了。这里顺便说一下CompletableFuture的异常处理因为这是网上问得最多的点。如果你在异步任务里抛了异常而主线程没有做任何处理这个异常很可能会被“吞掉”程序悄悄失败排障时非常难受。正确做法是给CompletableFuture链上加exceptionally或者用handle统一处理正常结果和异常。写成代码大概是这样CompletableFuture.supplyAsync(() - { if (Math.random() 0.5) { throw new RuntimeException(任务失败); } return ok; }).exceptionally(ex - { System.err.println(捕获异常 ex.getMessage()); return fallback; });笔试阶段不太可能要求你完整实现一个线程池但至少要看清核心参数的含义核心线程数、最大线程数、阻塞队列长度、拒绝策略。这几个参数经常被组合起来考比如“核心线程数5最大线程数10队列容量100来了200个任务最后一个任务会被执行还是拒绝”。很多人死记硬背但没有理清执行顺序先把任务放进队列队列满了才增加线程线程数到上限才触发拒绝策略。搞明白这个流程这类选择题基本就是送分题。异步编程准备方面我给出的建议是先掌握Runnable、Callable、Future这些基础抽象再学Executor和线程池最后才看CompletableFuture。如果急着上CompletableFuture又不理解线程池模型遇到异常处理、任务依赖、超时取消这些问题时很容易一头雾水。3. 笔试现场语言选择、时间分配和在线编辑器3.1 语言选择Java、Python还是C去哪儿笔试系统支持Java、Python、C、Go等主流语言开始前会先让你选定一门之后所有编程题都用这门语言提交。我当时选的是Java一是因为后端团队技术栈就是Java二是因为Java的集合框架在笔试阶段写起来比C省心而Python虽然代码量最短但有些在线笔试系统对递归深度有限制深搜类题目容易莫名其妙爆栈。如果你还在纠结选什么语言我的建议是用你最有把握的那门而不是用“最近看起来最流行”的那门。笔试时间很紧张切换语言带来的语法错误比切换算法思路更容易毁掉全场。如果岗位方向明确要求了语言比如Java后端那你就优先把Java并发布局、JVM基础、Spring常用注解这类八股准备扎实编程题也用Java写。另外如果你选择C笔试前一定把STL的几个常用容器过一遍vector、map、unordered_map、set、string的基本操作和复杂度。C在内存管理和裸指针上容易出bug但运行效率高适合图论、动态规划这类大规模数据题。Go的话要注意在线系统里Go版本差异有些新语法在旧版本编译器上不认。3.2 90分钟的时间分配和做题顺序我拿到试卷后的第一件事不是从头开始做而是先把四道编程题都扫一遍。这个动作很重要它能让你在脑子里快速形成一个难度排序。当时我扫完发现第一道是字符串时区转换第二道是连续子数组最大和第三道是图论邻接表遍历第四道是动态规划。我的做题顺序是先做第一、二道再做第三道最后剩多少时间就给第四道随缘。时间分配上我定的规则是选择题最多20分钟编程题每道最多15到20分钟超时就立刻止损跳到下一道。很多候选人挂在“非要把某道题AC”这个执念上结果最后一道简单的题都没时间写。笔试不是竞赛排名而是分数达标多拿一道题的分数往往比死磕一道难题更有价值。这里还要注意“部分分”策略。如果一道题的完整解法想不出来至少把暴力解写出来并提交只要它能过部分测试用例平台就会给你对应的分数。比如动态规划那题我最后只写了一个递归版本提交后大概过了30%的用例总比交白卷强。在真实笔试里这一两分的差距可能就决定你能否进入下一轮。3.3 在线编辑器里容易被忽略的细节在线编辑器是老生常谈但永远有人踩坑的地方。有些平台要求你写main方法有些平台只要求你补全一个函数有些平台用tab缩进有些平台用空格有些平台对类名有严格要求比如Main类首字母必须大写。这些细节看着小一旦编译报错花掉的时间远超想象。我考场上做的第一件事是先花两分钟做一次“空编译提交”把模板代码原样提交一次看它能不能通过编译。这个操作帮我发现了两个问题一是系统模板里已经包含了部分import但提交时不会自动带上所以自己的import一定要写全二是主类名默认是Main如果新建了一个类名必须要和文件名保持一致。这个习惯在后来好几场笔试里都救过我。另外在线编辑器通常没有代码格式化插件缩进和括号对齐全靠手动写的时候稍微注意一下变量命名和结构层次免得后续调试时看得眼晕。我习惯先把空方法签名和输入读取写好再往里面填核心逻辑这样即使最后没时间写完也能保证编译通过拿一个“编译正确”的最低分。4. 准备路线从刷题到契合岗位的进阶训练4.1 按公司风格刷题而不是盲目刷题不少人问春招编程笔试到底怎么准备我的回答是先从公司业务特点倒推题目方向。去哪儿是在线旅游平台核心业务包括机票、酒店、火车票、度假产品这些业务在技术层面的共性是订单状态流转复杂、库存和价格实时变动、并发量大、对接口的可用性和性能要求高。所以笔试题通常不会脱离数组、字符串、哈希表、图遍历这几个方向最多再加一道动态规划压轴。具体刷题时我建议按“专题限时”的方式推进而不是按题号顺序刷。比如给自己定一个周期这一周只刷数组双指针和滑动窗口下一周只刷动态规划。每做完一道题在笔记里记下解法和复杂度并尝试分析这个题目类型如果放在一个在线旅游场景里会对应什么问题。这样做的好处是在笔试现场看到题目时你能更快联想到相似的做题经验。“专题限时”还有一个好处它能帮你模拟真实考场节奏。比如每天花45分钟做两道中等题一道困难题时间到就停笔然后复盘。久了之后你对“一道题大概需要多久”会有精确的体感考场上就不会在某道题里死磕太长时间。4.2 异步编程、AI编程和工具链的补充学习除了算法题2023年还有一个绕不开的话题就是AI编程工具。笔试前一个月Cursor已经比较火了我也尝试过用它来辅助刷题比如让AI解释LeetCode题解里某一段状态转移方程的含义。这里想说一个比较现实的观点笔试现场不能用Cursor也不能用Copilot但准备阶段可以用它们来辅助建立题感尤其是你把一道题卡在原地超过20分钟的时候让AI用自然语言讲一遍效率会高很多。不过有个副作用就是容易让人产生“我随时能调AI手写能力不重要”的错觉。我在春招期间的约定是AI只做题解解释和错误分析不直接帮助写题一道题如果我先看了题解那一定会合上答案再独立默写一遍。准备阶段常见的AI提示词我会这么写“请用自然语言解释这段动态规划的转移方程并指出边界条件”或者“帮我检查这段代码在空数组输入下会不会越界”。这类提示词能快速提醒你注意易错点而不是直接把答案抄下来。如果你对异步编程和AI编程工具两件事都有兴趣可以做一个组合练习让AI生成一个异步任务处理的示例代码然后你自己手写一个带异常捕获和超时控制的版本最后对比差异。这个过程既练了CompletableFuture也练了代码阅读和评审能力比干刷题有意思得多。4.3 接触分布式MapReduce和HDFS的必要性如果你投的是大数据相关岗位那编程笔试之外还要准备MapReduce和HDFS的基础概念。去哪儿这类公司的日志分析、用户行为数据统计都会用到Hadoop生态。笔试不一定直接考但你的简历里如果写了大数据项目面试官大概率会顺着项目往细节问。MapReduce不需要你从零实现完整框架但至少要知道Map阶段和Reduce阶段各自负责什么Shuffle过程发生在哪个位置数据倾斜怎么处理。一个经典的例子就是词频统计Map阶段把每个单词变成(word, 1)的键值对Shuffle阶段按key分组Reduce阶段把相同key的value求和。听起来很简单但真正要落地时需要考虑数据分布不均、合并逻辑优化、磁盘IO开销等问题。HDFS则要掌握NameNode和DataNode的职责、默认副本数为什么是3、适合存储大文件但不适合大量小文件的场景。这些概念在笔试里经常以选择题形式出现比如“一个128MB的文件块默认复制3份总共占多少物理存储”。理解了副本机制这类题就是简单乘法。5. 典型坑位与排查技巧实录5.1 同一段代码本地没问题笔试系统却超时在线笔试里最典型的翻车现场是本地IDE跑测试用例全过一提交就开始超时。超时原因主要有三类第一类是时间复杂度过高数据量一大就崩第二类是死循环或递归深度过大第三类是频繁创建对象、频繁使用字符串拼接导致GC压力过大。我当时就有一次在循环里用了String 拼接数据量小的时候完全没问题数据量到10^5级别就直接超时。排查超时问题先别急着换算法而是去检查循环里有没有无意识的O(n²)操作。比如Java里list.contains()在ArrayList上是线性扫描如果你在一个外层循环里频繁调用它整体复杂度就可能变成O(n²)。这种情况下换成HashSet往往立竿见影。另外如果用到递归要检查递归树是不是重复计算了大量子问题如果是就改成带记忆化的动态规划。为了保险我在每次提交前都会额外做一个“边界自测”空数组、只有一个元素、最大长度随机数组、全负数数组。这四类输入能覆盖大多数边界问题比如Kadane算法里如果max初始值设成0遇到全负数数组就会出错。5.2 输入输出格式卡住无数人的隐形杀手很多时候题目本身不难难在看不懂输入格式。有些题目是多行输入但每行的字段分隔符可能是空格、逗号或制表符有些题目要求输出浮点数并保留两位小数有的要求四舍五入有的要求直接截断还有些题会把多组测试数据放在同一个文件里要求用while(scanner.hasNext())循环读取如果你只读了一组数据平台会判定只过了部分用例。我吃亏之后总结了一份checklist先看输入样例有几行每行几个字段字段之间用什么分隔再看输出样例是整数、浮点数还是字符串浮点数要保留几位最后看题目有没有明确写“多组输入”或“直到文件末尾”。这三个问题确认清楚再写代码能避免大量无谓的提交错误。在线编辑器里调试输入格式比较别扭因为你没法在本地随意构造文件。我的做法是先把样例输入写成字符串常量代码里直接读取该字符串测试逻辑等本地跑通后再改成从标准输入读取。这样做的好处是把“数据结构解析”和“算法逻辑”拆开验证定位bug会快很多。5.3 数组越界和空指针的快速定位限时场景下空指针和数组越界最烦人因为报错信息只给一个行号而线上平台又常常不允许你打断点。我常用的定位方式是“二分打印法”根据报错行号在关键变量和数组下标附近加print不断缩小定位范围。虽然多花一点时间但比对着代码瞎猜靠谱得多。另外我给自己定了三条硬规则凡是涉及数组下标的题循环一律用i n而不是i n凡是涉及字符串处理的题先判空再处理凡是涉及递归的题先确认终止条件能覆盖所有边界输入。这三条规则看起来很简单但它们能规避的报错远超想象。给一个常见问题速查表笔试前扫一眼很管用| 报错特征 | 常见原因 | 快速排查方向 | | 数组越界 | 循环边界写错或下标从1开始但数组从0开始 | 打印当前下标统一从0开始 | | 空指针 | 集合或对象未初始化或访问了不存在的key | 先判空再取值 | | 超时 | 复杂度太高或循环里隐藏O(n²)操作 | 用小数据集测边界再分析复杂度 | | 输出格式错误 | 多打了空格或小数位不对 | 与样例输出逐字符对比 |5.4 编译错误和类名命名问题在线笔试最常见也最憋屈的错误是编译失败。有些平台要求主类名为Main有些平台则允许你自定义类名但每道题的模板可能都不一样。如果你在编辑器里新建了一个类记得把类名改成题目要求否则提交时会直接编译错误。有些平台对包名也有要求模板开头可能有一行package千万不要删掉也不要手贱改成别的包名。有些平台会要求提交纯代码不能带有注释里的特殊符号所以在线的中文注释里尽量避免带分号、花括号等项目符号。6. 复盘一场笔试下来最该带走什么6.1 分数之外笔试暴露了哪些能力短板笔试结束不等于结束真正的成长在复盘。我的做法是趁记忆还热把每道题的思路写进笔记并标注自己属于哪一种完全没有思路、想到思路但没写完、写完了但bug一大堆。这样拆开之后后续复习就很有针对性没思路说明算法模型积累不够得补专题没写完说明代码熟练度不行得练手速写完有bug说明边界处理能力不足得多做小数据自测。这里也想说下企业筛选时的真实逻辑。虽然叫“编程笔试”但公司要考察的不只是你会不会写代码还包括代码风格是否规范、变量命名是否有意义、有没有基本注释、有没有考虑异常场景。这些细节在编程题横向对比时非常明显。两个人代码都能跑通但一份变量名全是a、b、c另一份拆成userIndex和maxSubSum后者的观感和可信度会高很多。我在复盘时还会用AI编程助手再造一遍题目场景。具体做法是给AI一段我自己写的笔试代码让它用code review的视角指出可读性、边界处理和复杂度问题。这比自己刷答案更能暴露盲点尤其是“变量命名不清晰”和“没有考虑null输入”这类问题AI通常能直接点出来。6.2 一些长期有效的方法论春招笔试这个阶段比较特殊你既要应付算法题又得准备语言特性和计算机基础还要分出精力关注行业里的新工具、新实践。我的经验是把它分成两条主线并行推进一条是数据结构与算法另一条是Java并发、操作系统、计算机网络、数据库基础。两条线每周都推进比把一本书啃完再换另一本更容易对抗遗忘。如果时间紧张至少要保证自己在90分钟内能完成两道中等难度热身题再留时间做一道动态规划或图论题。做到这个水平通过率就已经高过大部分在职和在校候选人了。平时刷题时尽量用没有自动补全的环境逼自己在裸写代码情况下保持手感笔试现场的很多紧张感其实都源于对手写代码不熟悉。最后再分享一个小技巧笔试结束后不管结果如何都把题目描述、自己的代码、标准解法三样保存到一个统一文件夹里。春招可能连续投多家公司很多题目类型会重复出现比如时区转换、连续子数组、订单状态统计这些沉淀下来的资料会在之后的秋招或实习申请时变成你独有的题库。我当时就是这样积累了几十份实战复盘第二场笔试明显比第一场稳多了。