2026/9/2 18:18:37

面了美团AI全栈开发,面试官让我写个合并两个排序链表,我笑了:“我刷题500道,苦练举一反三的能力,你就考我原题?”

面了美团AI全栈开发,面试官让我写个合并两个排序链表,我笑了:“我刷题500道,苦练举一反三的能力,你就考我原题?” 美团、字节、小米汽车今年都有考察 合并两个排序好的链表字节的面试官还特别强调了一下是否可以用递归。美团字节这道题目虽然简单也小细节也很多。21、 合并两个有序链表力扣链接https://leetcode.cn/problems/merge-two-sorted-lists/题目描述将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例 1输入list1 [1,2,4], list2 [1,3,4]输出[1,1,2,3,4,4]示例 2输入list1 [], list2 []输出[]示例 3输入list1 [], list2 [0]输出[0]提示两个链表的节点数目范围是[0, 50]-100 Node.val 100list1和list2均按非递减顺序排列思路两个链表本身已经有序怎么利用这个条件呢只需要比较两个链表当前节点的值谁更小就把谁接到结果链表后面然后让对应链表的指针向后移动一位。例如list1当前是 2list2当前是 3那么 2 一定是剩余节点中的最小值可以放心地把节点 2 接入结果链表。这里有两个问题需要想清楚。第一个问题结果链表的头结点怎么处理如果直接操作真正的头结点每接入一个节点都要判断结果链表是不是空。为了统一操作我们定义一个**虚拟头结点dummy**再用cur指向结果链表的尾部dummy固定不动方便最后找到结果链表的头结点cur始终指向已合并部分的最后一个节点list1、list2分别指向两个链表中还没有处理的第一个节点每轮循环只做三件事比较list1-val和list2-val把较小的节点接到cur-next移动被选中的链表指针再移动cur第二个问题如果一个链表先遍历完了怎么办另一个链表剩余部分本来就是有序的并且其中所有节点都不小于已经合并的节点所以不需要继续逐个比较直接把剩余链表整体接到cur-next即可。最后返回dummy.next因为dummy只是为了方便操作并不属于真正的结果链表。模拟过程以list1 [1,2,4]、list2 [1,3,4]为例。先创建虚拟头结点dummy令cur dummy。此时结果链表为空list1和list2分别指向两个链表的第一个节点。比较两个链表的当前节点。相等时我们接入list1的节点 1随后list1指向节点 2cur指向刚接入的节点 1。下一轮比较 2 和 1接入list2的节点 1。后续仍然按照相同规则依次接入节点 2、3、4。当list1已经指向空而list2还剩一个节点 4 时循环结束。直接执行cur-next list2结果链表就是[1,1,2,3,4,4]。很多录友写这道题时容易忘记最后接上剩余链表。想清楚循环条件是“两个链表都不为空”自然就知道循环结束后至少有一个链表为空还要处理另一个链表。解题代码迭代法class Solution {public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode dummy(0); // 虚拟头结点统一头结点的处理 ListNode* cur dummy; while (list1 ! nullptr list2 ! nullptr) { if (list1-val list2-val) { cur-next list1; list1 list1-next; } else { cur-next list2; list2 list2-next; } cur cur-next; } // 一个链表为空后直接接上另一个链表的剩余部分 cur-next list1 ! nullptr ? list1 : list2; return dummy.next; }};递归法递归写法要先明确当前应该返回哪个节点作为合并后链表的头结点如果list1-val list2-val那么当前头结点一定是list1。接下来只需要把list1-next指向“list1-next与list2合并后的结果”。另一种情况同理。class Solution {public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { if (list1 nullptr) return list2; if (list2 nullptr) return list1; if (list1-val list2-val) { list1-next mergeTwoLists(list1-next, list2); return list1; } list2-next mergeTwoLists(list1, list2-next); return list2; }};复杂度分析迭代法时间复杂度 O(m n)空间复杂度 O(1)。递归法时间复杂度 O(m n)空间复杂度 O(m n)空间消耗来自递归调用栈。其他语言Python3class Solution: def mergeTwoLists(self, list1, list2): dummy ListNode(0) cur dummy while list1 and list2: if list1.val list2.val: cur.next list1 list1 list1.next else: cur.next list2 list2 list2.next cur cur.next cur.next list1 if list1 else list2 return dummy.nextJavaclass Solution { public ListNode mergeTwoLists(ListNode list1, ListNode list2) { ListNode dummy new ListNode(0); ListNode cur dummy; while (list1 ! null list2 ! null) { if (list1.val list2.val) { cur.next list1; list1 list1.next; } else { cur.next list2; list2 list2.next; } cur cur.next; } cur.next list1 ! null ? list1 : list2; return dummy.next; }}Gofunc mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode { dummy : ListNode{} cur : dummy for list1 ! nil list2 ! nil { if list1.Val list2.Val { cur.Next list1 list1 list1.Next } else { cur.Next list2 list2 list2.Next } cur cur.Next } if list1 ! nil { cur.Next list1 } else { cur.Next list2 } return dummy.Next}学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】