ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

拼多多2023笔试真题全解析:算法考点、解题思路与刷题路线

2026/8/29 1:35:14 拓冰建站 浏览量
拼多多2023笔试真题全解析:算法考点、解题思路与刷题路线 每年秋招拼多多2023笔试真题集都会成为牛客网和脉脉上的热门资源。我整理这套题的原因很简单市面上流传的版本大多只有题面和答案没有解题思路复盘也没有难度评估和考点归类。这份真题集的价值不只是“做过一遍”而是把每一道题背后的算法模型、常见变体、边界陷阱都讲透让准备面试的人真正理解“拼多多到底在考什么”。这套内容适合三类人正在准备互联网大厂校招、需要系统练算法的同学想了解拼多多技术笔试难度梯度的职场人以及带了几年实习生、发现很多人代码写得出来但模型识别不出来的技术面试官。我会从题型结构、考点分布、五道典型真题的完整解法、刷题路线和考场避坑五个维度展开所有代码均以Python实现思路同样适用于Java和C。1. 拼多多2023笔试到底考什么一场“业务包装”的算法马拉松1.1 笔试形式与基础信息拼多多2023校招的在线笔试绝大多数批次采用的是 2 小时 4 道编程题的结构部分提前批批次会额外增加 10 道左右的行测逻辑题但分数权重远低于编程题。编程题运行环境是国内常用的牛客网和赛码网支持 Python、Java、C、Go 等主流语言但都是在线编辑器没有本地 IDE 的自动补全和断点调试。时间分配上4 道题目的难度通常是“简单 – 中等 – 中等偏难 – 难”。也就是说第一题大概率是让你稳定拿分的题目最后一题则承担区分度。很多同学倒在最后一题不是因为不会做而是前面题目消耗了太多时间导致最后一道能拿部分分的题没时间写。后面我详细说时间管理。1.2 题型分布与考点频率统计我对拼多多2023年的多次笔试批次技术岗做了统计编程题的考点分布大概是这个比例考点类别出现频率典型题目关键词贪心算法约25%资源分配、订单调度、最少次数动态规划约20%背包变体、区间DP、状态机DP二分答案 / 双指针约15%第K小/大、最小化最大值、滑动窗口栈与队列模拟约15%相邻消除、表达式解析、合并操作图论 / 搜索约10%最短路径、连通块、拓扑排序数学公式推导约15%组合计数、等差数列、取模问题这个分布说明一个问题拼多多不追求偏题怪题但非常看重基础算法在业务场景下的灵活运用。比如同一个“砍价”场景可以包装成贪心最少次数也可以包装成01背包求最大优惠关键是你能不能剥掉场景外壳。1.3 出题风格场景包装 弱样例 强边界拼多多的笔试题目有一个非常鲜明的特点把算法题包装成业务场景。“拼团”“砍价”“多多买菜配送”“仓库分拣”这些名词会频繁出现在题面里。但这只是包装剥开之后几乎都是经典的算法模型。另一个特点是样例输出通常给得非常“友好”可能只有一个 happy path。但实际数据范围却很大比如数组长度可以到 2×10^5此时 O(n^2) 的暴力解法必然超时。这个特性在面试者和刷题群里被反复吐槽也导致很多同学在自测样例通过后就直接提交最后拿到很低的分数。所以做题时一定要自己补充极端用例这个习惯我在第五部分重点展开。2. 真题题型深度拆解四类高频场景模型2.1 砍价与优惠券从“省钱”到“最优决策”拼多多题面里最经典的场景就是“砍价”和“优惠券”。我见过的变体包括给定若干张砍价券各自的砍价金额选择若干张使总减免不少于目标值求最少张数或者某商品有价格 P每张券有固定面额总面额不能超过 P 才能使用求最大能抵扣多少钱。这两类题表面相似但模型完全不同。前者是排序后从大到小贪心选券后者是容量为 P 的 01 背包问题。识别模型的关键词很简单问“最少几张”往往意味着贪心或二分问“最大价值”往往是背包或 DP。做题的时候如果发现两个模型都能套优先根据数据范围判断——背包容量如果很大比如 10^9那一定是贪心或数学解法而不是背包。2.2 拼团与组合最优排序 二分答案“拼团价”“三件打折”“多人成团均价最低”这类场景最终通常会落到“从数组里选若干个数求第 K 小/大的某个计算值”。最常见的是三数之和的变体任选三个数求和求所有组合中的第 K 小。这题如果暴力枚举所有三元组在 n2000 时就会产生约 13 亿组结果显然不可行。正确思路是二分答案猜测一个值 mid然后统计有多少组三元组的和小于等于 mid。统计过程可以用排序加双指针做到 O(n^2)整体复杂度 O(n^2 logV)。这类题目的识别特征是“第 K 小”“第 K 大”“不超过某个值”的组合计数。2.3 仓库物流与订单调度贪心排序 堆拼多多自营物流和多多买菜业务非常成熟所以笔试里大量出现配送、分拣、订单处理场景。常见模型是有若干个订单每个订单有处理耗时和截止时间同一时刻只能处理一个订单问最多能完成多少个。这个模型有一个非常经典的贪心解法——按截止时间从小到大排序用堆维护已选订单的耗时。每加入一个新订单就累加耗时如果总耗时超过当前订单的截止时间就移除已选订单中耗时最大的那个。堆里最后剩下的元素个数就是最多能完成的订单数。为什么这个贪心是对的呢因为截止时间越早的订单越紧急应该优先考虑而当不能满足时抛弃耗时最长的是一个“局部最优”的选择因为耗时越长越容易挤占其他订单的时间。这一步用最大堆实现每次替换复杂度 O(logn)整体 O(nlogn)完全能跑过 2×10^5 的数据范围。2.4 数据处理与合并栈与队列模拟最后一类高频考点是“相邻合并”“条件消除”“括号匹配变体”。拼多多如果出现这类题通常会把场景包装成仓库里相邻包裹才能合并、且合并后继续和下一个包裹比较等。这类题的通用解法是用栈模拟。从左到右扫描每个新元素不停地和栈顶比较如果满足合并条件就合并并把合并后的结果放回栈顶继续比较如果不满足就直接入栈。这个“只要栈顶满足条件就继续合并”的循环是关键很多同学漏掉这个循环导致只合并了一轮结果错了一半。3. 五道高频真题完整复盘从暴力到满分这五道题是我从真题集中精选的高频代表基本覆盖了上面四类模型。每道题我会给出题目描述、思路推导过程、完整代码和复杂度分析以及我实际做题时踩过的坑。3.1 题目一拼团三件商品的第K小优惠题目描述多多买菜活动有 n 个商品价格分别为 a[0], a[1], ..., a[n-1]。平台规定任选 3 个不同商品组成一个“拼团组合”组合价为三者的价格之和。请输出所有组合价中的第 K 个最小值从 1 开始计数。n 最大为 2000K 最大为 C(n,3)。解题思路最容易想到的是三层循环枚举所有三元组求出所有和再排序。但 n2000 时三元组数量约为 1.33×10^9 个直接枚举并排序在时间和内存上都是灾难。正确的做法是二分答案。因为我们要求“第 K 小的组合价”如果能高效计算“有多少组组合价 ≤ mid”就可以通过二分不断逼近答案。计数过程利用了排序数组的性质先对商品价格从小到大排序固定第一个数 i然后让第二个数下标 j 从 i1 开始第三个数下标 k 从 n-1 开始用双指针统计。如果 a[i] a[j] a[k] ≤ mid说明对于当前 jk 从 j1 到当前 k 的所有取值都满足条件所以计数加 k - j然后 j 右移否则说明当前 k 太大k 左移。参考代码def count_triples_le(a, mid): n len(a) cnt 0 for i in range(n - 2): j, k i 1, n - 1 while j k: if a[i] a[j] a[k] mid: cnt k - j j 1 else: k - 1 return cnt def kth_smallest_triple_sum(a, k): a.sort() n len(a) low a[0] a[1] a[2] high a[n - 3] a[n - 2] a[n - 1] while low high: mid (low high) // 2 if count_triples_le(a, mid) k: high mid else: low mid 1 return low复杂度与注意事项排序 O(nlogn)二分次数约为 log(最大和-最小和)每次计数 O(n^2)总复杂度约 O(n^2 logV)在 n2000 时可以稳定通过。这里有一个我复盘时发现的坑二分边界不能随便定成 0 或极大值最好取真实的最小三元组合和最大三元组合否则二分会多做几次不必要的循环。另外计数函数里的内层双指针是 O(n) 的外层 for 循环套着它整体是 O(n^2)这已经是最优了因为至少要检查一遍组合信息。3.2 题目二砍价券最少用几张题目描述有 n 张砍价券每张券可以砍 a[i] 元每张券只能用一次。现在有一件价格为 M 的商品问最少使用多少张券可以使砍掉的金额总和不少于 M。若所有券都用上仍不够输出 -1。n ≤ 10^5a[i] ≤ 10^9。解题思路又是一个看起来需要“想很久”的题实际上只要排序后从大到小叠加即可。为什么贪婪在这里成立因为每张券的“性价比”就是它自己的砍价金额没有额外限制也没有相互依赖关系。为了让总金额尽快达到 M优先选金额大的券一定最优。这种“单纯最大价值优先无约束”的题目就是典型的贪心入门题。参考代码def min_coupons(a, m): a.sort(reverseTrue) total 0 for i, v in enumerate(a): total v if total m: return i 1 return -1复杂度与注意事项排序 O(nlogn)扫描 O(n)。代码看起来很短但实战里很多人在最后一步踩坑如果所有券相加都不足 M要输出 -1 而不是返回 n 或者返回 0。另外注意数据范围a[i] 可以到 10^9n 到 10^5总和可能达到 10^14这时候在 C 里必须用 long longPython 没有这个问题但如果用 Java 就要小心 int 溢出。3.3 题目三仓库相邻包裹合并题目描述仓库里有 n 个包裹排成一行重量分别为 w[i]。两个相邻包裹如果重量差的绝对值不超过 k就可以合并成一个新的包裹重量为两者之和。合并后新包裹继续和它两边的包裹计算是否可以合并。问经过若干次合并后仓库里最少剩下几个包裹。n ≤ 10^5k 0。解题思路这道题看题面很像是区间 DP 的合并石子问题。但合并条件是基于重量差的绝对值而不是代价最小化且 n 到 10^5直接区间 DP 的 O(n^3) 肯定超时。正确解法是用栈模拟从左到右的合并过程。新包裹进入“仓库”时先和当前栈顶比较如果重量差 ≤ k就合并并把这个合并后的新包裹继续和新的栈顶比较直到不能合并或栈为空然后入栈。最终栈里的元素个数就是最少剩余包裹数。为什么从左到右的贪心合并是合理的因为每次合并不影响左边已经定型的包裹状态右边还没有进入栈的包裹唯一能和左边产生联系的方式是和新栈顶比较所以用栈维护当前“仓库末尾”的状态就足够了。实际笔试中这个思路属于中等难度偏易的代码题主要是要写对循环里的合并过程。参考代码def min_boxes(w, k): stack [] for weight in w: cur weight while stack and abs(stack[-1] - cur) k: cur stack.pop() stack.append(cur) return len(stack)复杂度与注意事项每个包裹最多入栈一次、出栈一次总复杂度 O(n)。这里最容易被忽视的是合并后的新包裹要“继续比较”很多人写成只比较一次就入栈导致可用合并漏掉。调试的时候建议用这组数据测试w [4, 6, 8], k 2。按题意4 和 6 合并得 1010 和 8 的差是 2还能再合并成 18所以答案应该是 1。如果只合并一轮答案会变成 2那就是合并循环没写对。3.4 题目四外卖订单最多完成数题目描述一个配送站有 n 个外卖订单每个订单有两个属性处理耗时 need[i]截止时间 dead[i]。配送站同一时间只能处理一个订单处理过程中不能中断。每个订单必须在截止时间之前或刚好在截止时间完成。问最多能完成多少个订单。解题思路这是经典的“任务调度最多完成数”问题。先按截止时间从小到大排序依次处理每个订单。用最大堆维护当前已选订单的处理耗时当前总耗时 cur 为堆内所有订单耗时之和。每处理一个新订单就把它的耗时加入 cur 并压入堆。如果 cur dead[i]说明在截止时间前无法完成全部已选订单这时从堆中弹出耗时最大的订单cur 同步减去它的耗时。注意弹出的不一定是当前这个订单可能是之前某个耗时很大的订单。为什么弹出耗时最大的因为我们要保证完成数量最大那么同样在“造成超时”的情况下踢掉耗时最长的订单能把总耗时压缩得最小为后续订单留出更多空间。而弹出的那个订单本身没有被真正完成所以堆的大小会减一。参考代码import heapq def max_orders(orders): orders.sort(keylambda x: x[1]) heap [] cur 0 for need, dead in orders: cur need heapq.heappush(heap, -need) if cur dead: cur heapq.heappop(heap) return len(heap)复杂度与注意事项排序 O(nlogn)每次堆操作 O(logn)总复杂度 O(nlogn)。这道题是一个典型的“反悔贪心”不是每一步直接决定选不选而是先“假设选择”当不满足约束时“反悔”上一个最差的选择。如果你第一次见这个思路可能会觉得代码难以理解我建议用几个反例手动模拟比如订单 [(2,4), (3,4)]如果只按截止时间排序后直接累加第一个订单耗时 2 完成第二个订单总耗时 5 超时此时把耗时 3 的订单弹出留下耗时 2 的订单最终完成 1 个而最优解其实就是完成第一个订单正确。3.5 题目五优惠券最大抵扣题目描述某商品价格是 P你有 n 张优惠券每张优惠券的面额为 v[i]。使用优惠券时可以选择任意张但所有优惠券面额之和不能超过商品价格 P否则无法使用。问在不超过 P 的前提下最多能用优惠券抵扣多少钱。P ≤ 50000n ≤ 1000v[i] ≤ 50000。解题思路把优惠券看成物品面额 v[i] 既是重量也是价值问题就变成一个标准的 01 背包容量为 P求能装下的最大价值。dp[j] 表示总面额不超过 j 时能获得的最大抵扣金额。由于重量和价值相同最终 dp[P] 就是答案。如果某张券面额正好等于 P那它可以直接“免单”。参考代码def max_discount(p, coupons): dp [0] * (p 1) for v in coupons: for j in range(p, v - 1, -1): if dp[j - v] v dp[j]: dp[j] dp[j - v] v return dp[p]复杂度与注意事项复杂度 O(nP)其中 P 是商品价格。P 给到 50000 时50000×1000 5000 万次循环在 Python 里大约 2 到 3 秒勉强能过如果 P 更大比如 10^9这个解法就完全不可行需要换思路——但那种情况下大概率是贪心或别的模型。所以做这类题时第一步先看数据范围再决定算法这是笔试中非常重要的判断力。4. 从真题反推的刷题路线高效的备赛策略4.1 必备知识点分级清单不是所有算法知识点都会被考到准备拼多多笔试优先级是分层的。我根据自己的刷题经验和真题统计把知识点分成三档优先级知识点必刷题类型第一档数组、字符串、哈希、排序、二分、双指针二分答案、三数之和、滑动窗口、TopK第一档贪心算法区间调度、任务分配、最少次数第二档动态规划01背包、完全背包、最长子序列、区间DP第二档栈与队列单调栈、相邻消除、栈模拟第二档堆最大堆/最小堆、贪心与堆的结合第三档图论最短路径、最小生成树、拓扑排序第三档数学组合计数、前缀和取模、快速幂第一档是必须拿满分的因为笔试第一题基本落在这里。第二档决定你能不能通过笔试——真题里的中等题基本都覆盖这些。第三档是加分项但准备时间有限时可以战略放弃部分冷门图论题。4.2 刷题量与节奏建议很多同学迷信“刷完LeetCode 300题就能过”我觉得这不是充分条件。拼多多2023笔试的题目难度比LeetCode Medium略低一点点但场景包装能力要求更高。我的建议是按专题刷而不是按题号刷。每个专题刷 15 到 20 题确保每道题都能独立讲出思路。模拟笔试也很重要。每周至少抽一个完整上午或下午找一套真题设好 2 小时倒计时模拟真实考试状态。这里的重点不是“做出来”而是检验你自己的时间分配、代码速度和心态。我记得我第一次模拟时在第二题上花了 50 分钟后面两题几乎没时间写后来调整策略把读题时间压缩到 5 分钟明显改善。4.3 “剥壳”训练把业务描述翻译成算法模型拼多多笔试最大的拦路虎不是算法本身而是“读题后不知道在考什么”。我建议平时刷题时每读完一道题的题面先用一句话写下“这题的算法模型是什么”再动手。举个例子题目说“多多买菜配送员有 n 个订单每个订单有体积和送达截止时间车辆一次装货有限额问最少几辆车能装完”。这句话翻译过来就是“箱子容量固定的最少装箱问题”但真正笔试中还会叠加“订单必须按片区顺序装车”这种限制那就变成了“连续区间分段最大化问题”。把包装剥掉剩下的都是你熟悉的模型。5. 考场上最容易翻车的实战问题5.1 样例过弱自测不足拼多多官方样例往往只有一到两组而且都是很温和的数据。比如题目二“砍价券最少用几张”样例可能只给一个“刚好够”的情况完全没覆盖“所有券都不够”的输出 -1 分支。应对方法是养成每道题至少构造三组自测数据的习惯极端最小数据n0/1/2、全相等数据、最大范围数据。这部分在代码里写注释或本地调试能救回大量分数。5.2 在线编辑器的输入输出细节拼多多笔试多数时候要求从标准输入读入输出到标准输出。要注意给定数据可能是多组测试用例需要用 while True 处理到 EOF题目如果没说明多组则一定是单组。另外输出行尾可以有空格但不能有多余换行否则部分评测机可能判格式错误。在线编辑器没有自动补全常用的输入解析模板一定要提前背下来。比如 Python 里 sys.stdin.read().split() 一次性读入所有数据再逐个解析通常比 input() 快也更不容易踩换行符的坑。5.3 时间分配策略我的经验是前 10 分钟把所有题都读一遍标记每道题的大致难度和算法方向。然后从最简单的题开始按“简单题 20 分钟、中等题 35 分钟、难题 40 分钟”的预算来做。如果超过预算还没思路果断放弃把时间留给后面的部分分。这里说的“部分分”非常重要。拼多多笔试一般按测试点给分几个简单测试点即使算法不是最优也能过。比如第 3.1 题三数之和如果你只能写出暴力三层循环建议也要写上可能能拿到 30% 的分数。空着和写暴力拿部分分的差距可能就是笔试是否能进面的差距。5.4 不要忽视数据范围导致的溢出和超时C 里 int 溢出是最常见的失误。题目给的数据范围如果超过 10^9求和就一定要用 long long。Python 虽然不会溢出但 O(n^2) 在 n10^5 时一定超时所以算法复杂度评估比语言选择更重要。做题前先看 n 的范围n10^3 可以用 O(n^2)n10^5 必须 O(nlogn) 或 O(n)n10^6 基本只能 O(n) 或 O(nlogn) 且常数要小。5.5 代码风格与可调试性笔试判分看的是测试点不是代码风格但好的代码风格能帮你更快定位 bug。变量命名用有意义的词核心逻辑加注释提交前顺手 print 几个中间变量调试。很多同学在第二题卡了很久最后发现是数组下标写错了一个单位这种低级错误在一个清晰的结构化代码里更容易被发现。我个人在实际操作中的一个很深的体会是做拼多多笔试最可惜的不是“不会做难题”而是“会做的题因为细节问题没拿满分”。2023 年这套真题集里几乎所有中等题都有至少一个类似的“小坑”分布在输出格式、-1 分支、边界数组、合并循环这些地方。如果你能把每一道题的最后几个边界用例都想清楚分数会明显和别人拉开差距。最后再分享一个小技巧把这份真题集当成“体检工具”每周抽出完整下午做一套不要边做边看题解。做完之后再对照题目后面的考点归类看自己到底在哪个模型上失分最多——是二分答案找不到单调性还是 DP 转移写不出来。针对性补强之后下一次模拟往往就能看到明显提升。这套方法不只适用于拼多多其他大厂的算法笔试也一样适用。