
去哪儿网的2016研发工程师编程题到现在还有人在翻出来看这件事本身就很说明问题。我自己在准备大厂面试时也刷过这套题坦白讲它的难度并不算顶尖但非常“典型”——典型的在线笔试出题风格、典型的业务场景包装、典型的坑点埋设。如果你正在准备互联网公司的研发岗笔试尤其是OTA在线旅游这一类的业务型公司这套题能帮你少走很多弯路。这篇文章就围绕这套题从考察逻辑、题型分类、经典题目推演、笔试实战策略几个角度来拆最后聊聊这套旧题在今天2025年的参考价值。1. 2016年去哪儿研发笔试在考什么一套题看清“题库型”面试的底层逻辑去哪儿网作为以机票、酒店搜索比价起家的在线旅游平台研发岗位的笔试题目一直有比较鲜明的业务导向。2016年那会儿校招笔试普遍采用在线OJOnline Judge系统题型以编程题为主辅以少量选择题。题目覆盖的知识点看起来并不高深但考察点非常精准你是否具备把实际问题抽象成算法模型的能力以及能否在有限时间内写出可运行、无死角的代码。1.1 为什么是“传统题型”而不是“高深算法”很多人拿到这套题的第一反应是就这数组遍历、字符串处理、基础DP连图论和高级数据结构都很少涉及。这其实是很多业务型公司的共性策略。面试官要筛选的不是竞赛选手而是能干活、能解决实际业务问题的工程师。去哪儿这类公司的业务场景大量涉及价格比较、航班组合、酒店排序、订单状态流转这些逻辑用数组、哈希表、排序、简单的动态规划就能建模。题目考得传统不是因为出题人水平不够而是因为这些传统题型恰恰最能反映一个工程师写业务代码的基本功。对比一下同期的BAT笔试题目就会发现去哪儿更重视“把题做对”而不是“把题做炫”。同样的知识点BAT可能考复杂的树形DP去哪儿会把它包装成一个“从一堆航班中找出转机时间最短的线路”这样的实际问题。能理解这个逻辑你就知道备战重点应该放在哪个方向。1.2 当时的环境OJ系统的输入输出陷阱2016年在线笔试系统已经比较成熟但远没有今天的牛客网、LeetCode那么友好。当时很多公司用的是自研的OJ系统或者第三方平台输入输出格式卡得很严多一个空格、少一个换行都有可能判错。我自己当年在另一家公司的笔试里就吃过这个亏题目要求输出用逗号分隔我输出成了空格全部WAWrong Answer但本地测试完全正常。这道题的输入输出部分有一个非常经典的设置——输入数据可能有多组。如果你只读一组就处理那只能过部分用例。正确做法是使用类似while (cin n)或者while (scanf(%d, n) ! EOF)这样的循环读取方式。这个细节放到今天依然是很多在线笔试的标配陷阱尤其是对于习惯了LeetCode核心代码模式只需要实现函数不需要处理IO的求职者来说更需要提前适应。去哪儿这套题里有不止一道题需要处理多行输入所以动手写代码之前先把输入输出格式确认清楚这比解题思路更重要。2. 高频题型拆解把去哪儿当年的几类“必考面孔”逐个说透我仔细研究过这套题里出现过的题目也参考了论坛上面经帖里的反馈基本上可以归成几个大类。这几个类别不是随便分的它们对应的正是这家公司业务中最常出现的计算逻辑。逐个拆开看你会发现每类的解题套路其实都很固定。2.1 字符串/数组处理处理输入的第一关字符串和数组是几乎所有在线笔试的第一道题标配。去哪儿这套题里字符串处理往往不是单纯的字符操作而是掺杂了业务语义。比如航班号、酒店ID、订单号这类数据的校验和解析本质上就是一个字符串处理的变体。常见考点包括字符串分割按逗号、空格、竖线等分隔符切开、子串查找与替换、字符串与数字的相互转换、去重统计。我当时做这类题目时总结了一个万能模板先用分隔符把整行字符串拆成一个字符串数组再逐段判断类型该转数字就转数字该做映射就做映射。# 以Python为例处理一行用逗号分隔的字符串提取其中的整数并求和 line input().strip() if not line: print(0) else: parts line.split(,) total 0 for p in parts: if p.strip().isdigit(): total int(p.strip()) print(total)这种代码在真实笔试里够用但放到去哪儿这种业务场景里往往要加一层包装。比如输入可能是“BJ123,SH456,GZ789”这样的城市编号格式你需要提取每个城市的编号并做汇总统计。这就不只是纯字符串操作了还涉及到结构体/字典的使用。关键在于这些题目做多了你会发现一个规律业务包装只是外衣内核永远是“读入—解析—计算—格式化输出”。只要你在二十行之内能把这个流程走通基本就能拿下一道题。2.2 排序与查找任何时候都绕不开的基本功去哪儿作为OTA平台排序逻辑在业务中无处不在。因此这套题里面有一个固定节目排序。但注意它不会让你写快速排序或者归并排序的完整实现而是考察你能否在理解排序的基础上写出正确的自定义排序规则。这类题目的典型表述是给定一批订单或者航班信息要求按某个字段降序排列如果该字段相同再按另一个字段升序排列。这种题目在C里可以用sort加自定义cmp函数解决在Java里则可以用Comparator。// Java版本按价格降序若价格相同按时间升序 Collections.sort(flights, new ComparatorFlight() { Override public int compare(Flight f1, Flight f2) { if (f1.price ! f2.price) { return f2.price - f1.price; // 价格降序 } return f1.time - f2.time; // 时间升序 } });这种写法本身不难真正容易踩坑的是排序的稳定性和比较器的一致性。Java的TimSort对compare方法的自反性、对称性、传递性有严格要求如果你的compare方法写得不严谨在极端的输入下可能抛出IllegalArgumentException(Comparison method violates its general contract!)。我见过真的有求职者因为这个原因在线上笔试里直接崩溃而本地测试却一切正常。所以在准备这种题时建议自己多测试几个边界case两个对象完全相同、整型最大值、负数的比较、含有null字段的情况。排序题永远不是“排出来就行”而是“任何输入都不能崩”。2.3 动态规划入门“能不能少写一重循环”2016年的去哪儿编程题已经涉及动态规划但难度梯度控制得很好基本上只考察一维DP和简单的二维DP。最典型的是“旅行花费最少”“抢票优惠最大化”这类最优子结构问题用一个一维数组就能定义状态。这类题目的套路非常固定核心就三步定义状态、找状态转移方程、确定初始化值和遍历顺序。以“连续区间最大收益”为例假设题面是某景点门票连续N天的价格你可以选择某一天买入、之后某一天卖出求最大收益也可以不操作视为0这其实就是经典的“股票买卖一次”的变形。初始化状态用一个变量minPrice记录截至目前的最低价格。用一个变量maxProfit记录截至目前的最大收益。遍历每一天的价格更新这两个变量。// Go版本一次遍历 prices : []int{7, 1, 5, 3, 6, 4} minPrice : prices[0] maxProfit : 0 for i : 1; i len(prices); i { if prices[i] minPrice { minPrice prices[i] } else if prices[i]-minPrice maxProfit { maxProfit prices[i] - minPrice } } fmt.Println(maxProfit)这种解法的时间复杂度是O(n)空间复杂度是O(1)已经是最优解了。但很多人一上来会先写一个O(n²)的两重循环版本这当然不错只是效率低。笔试的时候如果你只能想到暴力解法没问题先把暴力写出来拿部分分然后再优化。这套策略在去哪儿这类不是“非对即错”判分的公司特别管用——能拿部分分的题目就不要交白卷。3. 一道完整真题推演从读题到AC的全过程上面几类题型都说的是面子这一段我挑一道非常有代表性的题目完整推演一遍从读懂题到最终提交的整个思考过程。这道题在很多面经里都出现过算是一道高频题。题目大意是给定一个整数数组代表连续若干天的航班价格也可能代表股票价格业务包装不同而已你只能买卖一次先买后卖求最大收益。如果无论如何都不能盈利返回0。3.1 第一版暴力解法先确保能跑拿到题第一步先把最朴素的想法写出来。既然只能买卖一次那我可以枚举买入日i和卖出日jj i用prices[j] - prices[i]算收益取最大值如果最大值小于0就返回0。public int maxProfit(int[] prices) { if (prices null || prices.length 2) { return 0; } int max 0; for (int i 0; i prices.length; i) { for (int j i 1; j prices.length; j) { if (prices[j] - prices[i] max) { max prices[j] - prices[i]; } } } return max; }两重循环时间复杂度O(n²)。对于2016年的笔试题目数据规模通常在几百到几千O(n²)完全能过。很多人觉得暴力解法不够专业但真实笔试中先拿到AC再谈优化永远是第一原则。一旦把暴力解法写出来你心里就有底了后面再怎么优化都不会慌张。3.2 第二版一次遍历的状态维护暴力解法提交之后如果数据规模很大导致超时再考虑优化。这时候可以回到刚才的思路在遍历到第i天时只有两种情况——这一天作为卖出日如果之前有过更低的买入价或者这一天作为未来的买入候选日。因此用两个变量就够了。minPrice保存遍历至今的最低价格maxProfit保存遍历至今的最大收益。每次遇到比minPrice更低的价格就更新minPrice否则尝试用当前价格减去minPrice看能不能刷新maxProfit。def max_profit(prices): if not prices or len(prices) 2: return 0 min_price prices[0] max_profit 0 for price in prices[1:]: if price min_price: min_price price else: max_profit max(max_profit, price - min_price) return max_profit这个解法在本质上就是一个“滚动状态”的思路你不关心过去具体哪天买的只关心过去的最小值。这种把历史状态压缩成一个变量的技巧在很多一维DP问题里都适用。比如“连续子数组最大和”Kadane算法就是同一类思想的体现。3.3 边界用例与提交前的自测清单AC率低的真正原因很多时候不是思路错而是边界没考虑清楚。我在刷这套题的时候每次写完代码都会先在心里跑一遍这几个用例空数组[]返回0而不是抛异常。长度只有1的数组[3]返回0因为买不了也卖不了。价格持续下跌[5, 4, 3, 2, 1]任何操作都亏返回0。价格持续上涨[1, 2, 3, 4, 5]应该返回4第一天买、最后一天卖。最大差值出现在最后两天[2, 4, 1, 7]应该在价格为1时买入、价格为7时卖出返回6。存在相等价格[2, 2, 2, 2]返回0。这些用例在本地编译器里跑一遍最多花两分钟但能避免80%以上的提交失误。很多求职者就是因为没有这个习惯在OJ系统上白白浪费提交次数。在线笔试系统一般会有错误提示但不会告诉你具体哪个用例挂了所以事先自测就显得尤为重要。4. 在线笔试的实战策略时间分配、语言选择、代码规范把题目本身拆完之后我想聊一些更“虚”但同样重要的东西。编程题解题能力是基础但能否在在线笔试环境中把能力完全发挥出来是另一回事。去哪儿这套题的难度梯度设定得比较合理一般会有2~3道题总时长在90分钟左右。如果你按照“简单题20分钟、中等题30分钟、挑战题40分钟”的节奏来分配会比较从容。4.1 语言怎么选C/Java的优劣2016年那会儿的在线笔试系统主流支持C/C和JavaPython虽然已经开始普及但部分OJ系统对Python的支持还不算稳定。到了2025年绝大多数在线笔试平台都支持Python、Go、JavaScript等语言但C和Java依然是“最稳”的选择。选语言的核心原则是选你最熟的那门而不是选看起来最优雅的那门。如果你平时写Java多笔试时就不要强行切C即使C的std::sort写起来更简洁。你的目标是快速、准确地解决问题而不是展示语言切换能力。我个人的建议是准备两门语言一门自己最熟的作为主战语言另一门作为备选。Java选手需要格外注意类名、方法签名是否符合OJ要求比如很多OJ要求主类必须是Main方法必须是public static void main(String[] args)。import java.util.*; public class Main { public static void main(String[] args) { Scanner sc new Scanner(System.in); while (sc.hasNext()) { int n sc.nextInt(); // 处理逻辑 } sc.close(); } }这段代码里的while (sc.hasNext())是处理多组输入的关键很多第一次参加在线笔试的人会漏掉。4.2 读题顺序与时间分配策略拿到卷子先把所有题目的题干快速扫一遍。这个动作只需要三分钟但能帮你建立起对整个卷子的全局认知。哪道题简单、哪道题复杂、哪道题分值高一目了然。然后按照“先易后难、先拿分再拿满分”的顺序做题。我特别想提醒一点如果一道题你看了十分钟还没有任何思路果断跳过做下一道。不要死磕。在线笔试的时间成本很高死磕一道题可能导致后面所有题都没时间做。正确做法是先把所有能拿的分都拿到剩下的时间再回头啃硬骨头。4.3 调试技巧和输出格式的坑在线笔试的调试能力和本地IDE调试完全不同因为没有断点、没有监视窗口你只能靠print输出中间变量。这时候一个好的调试习惯是在关键节点输出中间结果确认后立刻删掉这些调试代码避免干扰最终输出。输出格式的坑更是层出不穷。常见的有行末多余空格、大小写不一致、整数溢出、浮点精度问题。以整数溢出为例如果题目中数据范围没说默认都用int但在计算累加和或差值时可能超过int上限2³¹-1。稳妥起见涉及累加和比较的变量直接用long。2016年的题目里就出现过“航班总里程累加”这种看起来人畜无害、但用int就会溢出的题。5. 这套题的参考价值给2025年备战者的建议距离2016年已经过去将近十年技术栈都换了好几轮为什么这套题还有人在翻因为在线笔试的考察逻辑几乎没有变过。不管AI工具发展到什么程度企业招人时仍然需要确认候选人的基础编码能力、逻辑思维能力和边界处理意识。一套旧题的参考价值恰恰在于它去除掉了所有花哨的包装留下了最本质的考察点。5.1 题型在变考察的底层能力没变对比2016年的去哪儿笔试题和2025年各大厂的校招笔试题最明显的变化有两点一是题量通常增多二是可能引入一些偏工程化的场景题比如设计一个短URL服务。但底层能力框架没变依然是数据结构、算法、边界处理、IO处理这四个维度。今天你在LeetCode上刷的“买卖股票的最佳时机”就是2016年那套题里“航班价格最大收益”的直接后代。题型变了包装内核没变这提醒你备战时要更注重底层能力的沉淀而不是追逐题目表面的新颖程度。5.2 用“一套旧题”做“三轮复习”的具体操作如果你现在准备参加2025年的秋招或者社招笔试怎么用这套旧题做高效复习我的建议是按三轮走第一轮全真模拟。找出连续90分钟的整块时间严格按照在线笔试的规则用OJ系统牛客网就有这题的原题汇总完整做完一遍。该读题读题该写码写码不要中途查资料。做完之后统计自己的得分率和用时。第二轮逐题深挖。第一轮做完之后不急着刷新题而是把这套题里每一道题都拿出来逐题复盘。问自己三个问题这道题的考点是什么我当时为什么会在某个地方卡住如果我重新做一遍能不能在更短时间内完成把每个题解都整理成笔记写成题解文章更好。第三轮举一反三。用“一题变三题”的方式巩固把“航班价格最大收益”变成“任意多次交易的最大收益”把“订单按价格排序”变成“订单按多个条件混合排序”把字符串解析题改成解析JSON格式。每道题都自己变形一次你对这个知识点的理解就会比单纯刷题深得多。我自己在辅导别人准备笔试时一直强调一个概念刷题的量不重要重要的是你是否形成了“看到题目就能快速归类到某个知识点”的条件反射。这套旧题一共就那么多道如果你能每道题做到这个程度花在上面的时间绝对物超所值。5.3 关于Python和2025年的新趋势前面提到2016年那会儿Python在OJ系统上支持度有限到了2025年Python已经成了在线笔试的“默认选项”之一。很多求职者在笔试时会选择Python来写图的就是语法简洁、开发效率高。这是一个好趋势但也要注意Python的隐藏坑并不少比如大整数性能和递归深度限制默认递归深度约1000层如果题目考察DFS递归遍历二叉树深度一大就可能在递归中爆栈需要用迭代写法代替。所以选择Python答题前先把这些边界问题摸清楚。另外现在的AI编程助手已经很强大但真实笔试环境越来越强调“反作弊”和“屏幕录制”指望靠辅助工具答题既不现实也不诚实。真正稳妥的路线还是把基础题型吃透做到快速、准确地手写代码。这套2016年的旧题恰恰是练习“快速手写”的绝佳素材——题量适中难度有梯度考察点集中不会让你陷入“刷题两小时、全是重复内容”的低效循环。按我个人的经验笔试从来不是比谁懂得多而是比谁在有限时间里犯错少。把一套有代表性的题反复打磨到每道题都能稳定AC远比囫囵吞枣刷几百道新题更有价值。这套2016年去哪儿研发工程师编程题就是这样一个值得反复打磨的样本。如果你正在准备互联网公司的研发岗笔试不妨从这个起点开始。