上周刚把Intuit 2026届的OA做完,趁热打铁记录一份复盘。Intuit OA每年都有人问,但全网信息其实挺散:有人说是纯算法,有人说不止算法。我这次实际做下来的体感是,核心就是两道中等偏上的coding题,平台用的HackerRank,总时长以邮件为准,我收到的是90分钟。这篇主要想帮正在准备Intuit OA的朋友省点信息差,尤其是那种“投完简历不知道什么时候来OA、来了OA不知道刷什么题”的焦虑状态。我会尽量把题目还原、解题思路、踩坑点、时间分配都写清楚,纯经验分享,希望能对你有用。
需要先说一句,题目是我凭记忆还原的版本,描述顺序和原题可能有出入,但数据结构、解法套路、边界条件这些是可以放心参考的。复盘的价值不在于背原题,而在于弄懂Intuit这类OA到底在考你什么,以及如何在有限时间里稳定发挥。
1. 整体解读:2026届Intuit OA到底在筛选什么
1.1 为什么说OA是“简历之后的第一道坎”
很多同学容易把OA当成一次普通的算法考试,其实站在招聘方的角度,OA是成本最低、覆盖面最大的筛选手段。Intuit作为做TurboTax、QuickBooks、Mint这些产品的公司,工程岗的简历量一直不小,HR没精力让每个人都进入面试,所以OA承担的角色非常直接:把“能写代码、能解算法题、能在压力下处理边界情况”的人筛出来。2026届的OA,我体感上比往年更强调“正确性和可读性并重”。
这一点非常重要。我在做题过程中发现,HackerRank平台上会有多个预置测试用例,运行后能看到哪些过了哪些挂了,但看不到别人的解法。也就是说,这道题评判的不是你思考过程多精妙,而是你最终交上去的代码是否在时间限制内通过了所有隐藏用例。所以要尽可能一次写对,尽量避免第一遍暴力、第二遍优化的“试错式答题”,因为时间真的会不够。
1.2 我这次OA的时间线、平台与题型构成
先交代一下背景:我是提前批投递的Intuit SWE岗位,大约一周后收到了OA邮件。邮件里给的是HackerRank链接,点进去先是一段简短的说明页,包括考试总时长和题目数量。我这次是90分钟两道coding题,语言任选,我选了Java。不同批次可能有差异,有人收到的可能是75分钟或120分钟,以邮件为准,关键是收到后别拖,越早做越不容易和别的安排撞车。
两道题给我的整体印象是:第一题看起来不难,但边界条件很细;第二题中等偏上,核心是经典套路,但需要你把题目抽象出来。整体风格偏向“业务场景包装 + 数据结构核心考察”,没有偏题怪题,也没有特别复杂的图论或高级动态规划。只要你把高频算法模块复习扎实,是能稳住的。
1.3 两道题背后的共同考点
做完之后我回头总结,发现这两道题虽然描述完全不同,但本质上有几个共同点:
- 都考“能不能把一个业务问题抽象成已知的数据结构问题”。
- 都考“边界条件意识”,比如区间端点是否包含、数组元素是否可能为负数、累加结果会不会溢出。
- 都考“复杂度意识”,第一题如果你用暴力比较所有区间,O(n^2)在数据量大时会超时;第二题如果你用双指针,遇到负数直接失效,必须转前缀和。
所以,如果你现在还在刷题阶段,建议别只盯着“AC数量”,多问自己一句:这个题最优解为什么长这样?我下次换个业务背景还认不认得出来?
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 真题复盘(一):最大并发区间数,业务外壳下的排序扫描
2.1 题目回忆:顾问会话调度中的重叠统计
我遇到的题目给了一个比较常见的业务场景,大意是:有一批客户与财务顾问的线上会话记录,每条记录包含会话开始时间和结束时间,需要计算在任意时刻同时进行的最大会话数量。数据输入是一个二维数组,每一行是[ start, end ],start和end都是整数时间戳,区间是左闭右开,也就是说start时刻会计入该区间,end时刻不算。输出一个整数,表示最大并发数。
这个题其实是LeetCode上很经典的“会议室II”或“最大重叠区间数”的变体。因为Intuit做财务软件,这类会话调度、预约并发场景出现频率不低。它考察的核心是:能否把区间问题转化成事件扫描问题,并正确处理同一时刻有区间结束和开始的情况。
2.2 从暴力到最优:为什么第一时间应该想到事件扫描
最直观的解法是:枚举每个时间点,数一数有多少区间包含这个点,然后取最大值。但这样做复杂度取决于时间范围,如果时间戳范围是百万级甚至更大,就会非常不可控。再有一种直觉是两两比较区间是否重叠,然后想办法求最大重叠数,但这也容易做成O(n^2)。
正确做法是把每个区间拆成两个事件:区间开始是一个“+1”事件,区间结束是一个“-1”事件。然后按时间顺序遍历所有事件,用一个变量cur记录当前并发数,遇到开始就加1,遇到结束就减1,过程中最大的cur就是答案。
这里有一个很容易翻车的点:当同一个时间点既有区间结束又有区间开始,应该先处理结束还是先处理开始?由于区间是左闭右开,end时刻该区间已经结束,而另一个区间的start时刻刚开始,两个区间在这个点上不应该算作重叠。所以排序时必须保证同样时间下“-1事件”排在“+1事件”前面,也就是先减后加。理解了这一点,代码才不容易写错。
2.3 参考代码实现
java复制public int maxConcurrentSessions(int[][] sessions) {
// 每个事件:events[i][0] = 时间点, events[i][1] = +1开始 / -1结束
int n = sessions.length;
int[][] events = new int[n * 2][2];
int idx = 0;
for (int[] s : sessions) {
events[idx][0] = s[0];
events[idx][1] = 1;
idx++;
events[idx][0] = s[1];
events[idx][1] = -1;
idx++;
}
Arrays.sort(events, (a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
int cur = 0;
int max = 0;
for (int[] e : events) {
cur += e[1];
max = Math.max(max, cur);
}
return max;
}
如果你不喜欢事件数组,也可以用优先级队列:先按start排序所有区间,然后维护一个小顶堆,堆里放当前重叠区间的end。遍历每个区间时,先弹出所有end <= 当前start的区间,再把当前区间的end放进堆,堆的大小就是当前并发数。这个方法同样直观,本质上也是扫描线的另一种写法。
需要特别注意,如果输入的时间戳范围很大,但区间数量不大,事件扫描法只和区间数量有关,时间复杂度O(n log n),空间复杂度O(n),这是最优且最稳的方案。
2.4 复盘笔记:我在这题上踩到的“隐含条件”
这题通过率其实不低,但想要一次通过还是有细节的。我第一次写完事件数组排序后,直接按时间正序排列,没有让同时间的结束事件排在开始事件之前,结果示例里如果出现[5,10)和[10,15)这种紧挨着的区间,我错误计算成了2。发现问题后,我改成sort里增加第二关键字,按事件类型升序,也就是让-1排在+1前面,这个小改动直接影响正确性。
另外,如果原题给的不是int时间戳,而是带时区的字符串,比如“2026-03-01 09:00”,解析成分钟或毫秒数再处理会省去很多字符串比较的麻烦。注意日期字符串的格式不一定统一,有些可能是“MM/dd/yyyy HH:mm”,有些是ISO格式,解析前最好先看一眼样例,或者用一个helper method统一处理。别在这种地方浪费不必要的调试时间。
3. 真题复盘(二):连续子数组和等于目标值的方案数,前缀和的经典套娃
3.1 题目回忆:交易对账场景下的“目标金额”
第二题描述也套了一层业务背景,大概意思是:有一串连续交易金额,可能包含负数,现在要对账,目标是一个整数k。要求计算出有多少个连续子数组的和恰好等于k。这题包装成什么样不重要,剥掉外壳就是“给定一个整数数组nums和一个整数k,返回连续子数组和为k的子数组个数”。
和第一题相比,这题更考察对前缀和与哈希表结合的熟练度。为什么不能用滑动窗口双指针?因为数组包含负数。滑动窗口的前提是窗口的扩展和收缩方向与和的单调性一致,但负数破坏了这个性质。比如当前窗口的和小于k,你可能以为往右扩一个负数会更小,但后面接一个更大的正数又可能刚好凑成k,这种非单调性让双指针无法正确缩进。
3.2 解法推导:前缀和为什么能把题目变成“找差值”
先说结论:连续子数组的和等于末位置前缀和减去起始位置之前的前缀和。如果定义一个数组prefix[i]表示从0到i的所有元素之和,那么从j+1到i的子数组和为prefix[i] - prefix[j]。我们要找prefix[i] - prefix[j] == k,等价于找每个位置i之前有多少个j满足prefix[j] == prefix[i] - k。
这个视角把“区间和”问题转化成“前面出现过多少个特定前缀和”的问题。由于每次只需要统计当前前缀和之前已经出现过哪些值,用HashMap记录“前缀和 -> 出现次数”是最自然的选择。遍历数组时,先查map里有没有prefix - k,有就把对应次数加入答案,然后把当前prefix放入map,次数加1。要注意初始时map中要放(0, 1),因为一个元素都不取时前缀和是0,这对应了从数组开头开始的合法子数组。
3.3 Java参考实现
java复制public int subarraySum(int[] nums, int k) {
// key: 前缀和, value: 出现次数
Map<Integer, Integer> prefixCount = new HashMap<>();
prefixCount.put(0, 1);
int prefix = 0;
int ans = 0;
for (int num : nums) {
prefix += num;
int target = prefix - k;
ans += prefixCount.getOrDefault(target, 0);
prefixCount.put(prefix, prefixCount.getOrDefault(prefix, 0) + 1);
}
return ans;
}
如果你担心前缀和累加超出int范围,可以把prefix声明为long或Long,Map的类型改成Map<Long, Integer>。HackerRank上对Java的memory检查比较宽松,但不代表可以忽略溢出隐患。我一般习惯直接使用long,因为OA环境里不会因为这一点点内存差异判错,却能避免溢出带来的隐藏错误。
另一个容易踩的点是在取target的时机。一定是先统计,再把自己当前的prefix放进map,顺序反了的话,会错误地把当前子数组也算进去,导致结果偏大。这里不是多一行代码的问题,而是对“历史和现在”的区分。和它对应的还有一种变体问法:求最长的连续子数组和为k的长度,这时候HashMap存的就不是“次数”,而是“前缀和第一次出现的位置”,代码逻辑和这题相当接近。
3.4 边界条件详解
这类前缀和题目最常见的三个边界条件分别是:k为0、数组只有一个元素、前缀和出现负数。k为0时,map(0,1)的初始值非常重要。比如数组是[1,-1,0],目标是0,正确解应该有[1,-1]、[0]、[1,-1,0]共3个子数组,如果不初始化map(0,1),会漏掉第一个从开头开始的子数组。数组只有一个元素时,逻辑同样依赖前缀和差值的正确性,代码能cover住,不需要单独写if分支。前缀和为负数也完全没问题,HashMap用Integer做key时负数就是普通的键。
最后补充说一点,这题的输入规模在OA里通常会达到10^5,暴力枚举所有子数组的O(n^2)必然超时,而前缀和加HashMap是标准的O(n)解法。所以看到连续子数组和、目标值、可能负数这三个特征,应该条件反射地想到前缀和。
4. 作答实操:HackerRank环境下的时间分配与调试方法
4.1 平台环境观察
HackerRank作为在线评测平台,界面通常是左边题目描述、右边代码编辑区,有时需要你自己读标准输入或已经帮你封装好了方法。Intuit的题一般是直接实现一个方法,不需要处理标准输入输出,这个对国内刷习惯LeetCode的同学很友好。但要注意,有些版本会隐藏一些测试用例,你只看到几个示例和通过状态,看不到具体输入数据,所以自己构造边界样例的能力就很重要。
还有一点,HackerRank的自动补全很弱,如果你平时依赖IDE的智能提示,建议在OA开始前用HackerRank的官方practice题练几道,让自己适应这个手感。否则你会突然发现连ArrayList的import都要手写,虽然不扣分,但会打断思路。
4.2 我的时间分配方案
两道题90分钟,一开始不要直接扎进第一题。我采用的时间分配大致是这样的:
| 时间段 | 任务 |
|---|---|
| 前5分钟 | 快速浏览两道题,确认题干和输入输出,给题目难度排序 |
| 5-10分钟 | 开始处理第一题,先想清楚算法和边界条件 |
| 10-40分钟 | 写第一题,跑示例和自己补充的边界用例 |
| 40-45分钟 | 从第一题抽离,快速看一下第二题样例,构思方案 |
| 45-70分钟 | 写第二题,跑尽量的额外用例 |
| 70-85分钟 | 复查两道题,补漏边界条件,检查类型溢出 |
| 85-90分钟 | 最后确认提交格式,切忌赶在最后一分钟改动大段代码 |
这个方案的核心是:先通读所有题,而不是按顺序死磕。如果第二题比第一题简单,完全可以先做第二题,得分优先。我的习惯是写一道题时就专心写,不切出去想另一道,但一定要留出整块的复查时间。
4.3 调试时的三个习惯
第一,多打印中间值。OA环境里print到console不算错误,我遇到复杂样例过不去时,会把前缀和数组或事件列表打出来,手动对一遍。第二,自己构造极端用例,比如“两个区间首尾相接”“数组全部为负数”“数组只有一个元素”。把所有edge case在本地跑一遍,通常能修复大部分隐藏bug。第三,如果运行超时,先看是不是复杂度问题,再看是不是死循环。事件扫描和前缀和这两个模板都不应该出现O(n^2)的代码,如果超时,通常是排序比较器写得不对,或者HashMap在频繁自动装箱时不会慢到超时,还是优先检查算法结构。
5. 高频翻车点与变体预警
5.1 常见问题速查表
这段时间在论坛和群里看大家讨论,把一些高频问题汇总成了表格,方便你自查:
| 现象 | 常见原因 | 解决思路 |
|---|---|---|
| 第一个测试用例就错 | 区间开闭理解错,或同时间事件排序没处理 | 统一用[start,end),先处理结束事件 |
| 数组全负数时双指针解不对 | 误用滑动窗口 | 看到负数应想到前缀和 |
| 前缀和答案多算或少算 | prefix入map时机不对 | 先统计目标前缀,再把当前前缀放入map |
| 字符串时间戳解析慢 | 日期格式不统一 | 提前写好统一parse方法,转成long |
| 暴力方法超时 | 复杂度太高 | 把O(n^2)降到O(n log n)或O(n) |
| 结果溢出 | int累加越界 | 用long存前缀和或并发数 |
这里要特别强调,HackerRank的判分会对部分隐藏用例卡时间,如果你的解法复杂度不对,即使能跑通小样例也会在隐藏大数据上超时。所以写代码前先在注释里写自己是什么复杂度,如果高于O(n log n),大概率不是最优方向。
5.2 两道题常见的变体版本
据我了解,Intuit OA题库里这两类题都有不少变体。第一题可能变成:给一串会议时间,问需要多少个会议室;或者给一段查询时间,问每个时间段内有多少个会话正在发生。前者和最大并发数本质上相同,后者则可以用差分数组或事件扫描后二分处理。
第二题的变体可能会变成:求最长的和为k的连续子数组长度、和为k的子数组数量、存在不存在和为k的连续子数组、或者改成二维矩阵中找某个子矩阵和等于target。如果你只背了原题模板,遇到一变可能就慌。我的建议是理解前缀和的核心思想,也就是“把区间和转化为两个前缀和的差”,这样无论问数量、长度还是是否存在,你都能用它去推理。
5.3 关于后续流程,说点个人观察
做完OA之后,我翻了往年不少帖子,发现Intuit的招聘流程大概率是OA之后接技术电话面试,也可能有pair programming这一轮,不同team会有差异。OA结果不是面试的唯一依据,但code整体的结构和注释会影响之后面试官对你的初印象。所以我建议在OA里也保持“可作为简历样本”的意识,变量命名清楚,逻辑分层明确,即使只有一个方法也能看出你的工程习惯。别为了压缩代码写出全是缩写变量的版本,能看懂比显得聪明重要。
6. 我最后想分享的备考建议
6.1 两周冲刺怎么安排
如果距离OA只剩两周,不建议再盲目刷新题了,优先级应该是:回归高频题型模板、做公司tag题、猛练手写代码手感。每天保持两道Medium题量的同时,把以下类型挨个过一遍:区间问题、前缀和、滑动窗口、双指针、DFS/BFS、拓扑排序、二分答案、优先队列。Intuit的OA题目难度整体不会超过Medium,重点不在偏题,而在于基础题型是否熟练。
6.2 常用资源组合
资源我推荐三样:第一,LeetCode公司tag里搜Intuit,看一下最近高频题,不必全刷,按频率从高到低刷30题左右;第二,HackerRank官方算法练习,主要熟悉平台交互,尤其是代码编辑和测试用例输出形式;第三,一套高频模板笔记,比如前缀和模板、并查集模板、二叉树遍历模板,临考前翻一翻比新刷题更有用。
另外别忽视语言本身的细节。如果选Java,HashMap的merge、getOrDefault、computeIfAbsent这些方法要熟悉;如果选Python,dict的defaultdict和Counter要顺手。编码速度在OA里非常影响心态,因为一旦卡住一个语法细节,整个节奏就会乱。
6.3 一个提高稳定性的小技巧
这个方法很多人不知道:拿到题后,不要立刻动手coding,先在草稿纸上把枚举一个小例子的过程写出来,模拟一遍自己想用的算法。比如第二题,你可以随手写一个nums=[1,-1,0],手动算一下前缀和变化,再翻译成代码。这个过程看起来浪费两分钟,但实际上能让你在写之前就发现很多语义理解错误。我在这次OA里就是先跑了一个小例子,才发现第一题我最初的理解把开闭区间搞反了。
如果你也在准备2026届的Intuit OA,希望这篇复盘能帮你减少踩坑。最后再提一句,OA只是起点,保持稳定发挥,把基础模板吃透,比押中某道原题重要得多。祝顺利。
