仓颉语言实现 LeetCode 第 2 题「两数相加」:Option 模式匹配与链表进位迭代详解
示例工程教育【免费下载链接】Exercises本仓收集仓颉算法题解程序项目地址https://gitcode.com/Cangjie/Exercises点击查看免费下载本篇以 Exercises 仓库中的仓颉Cangjie题解 【Leetcode】2.两数相加/readme.md 为主线完整还原「用链表模拟两个非负整数相加」的解题思路与逐行源码剖析并结合仓颉特有的Option类型、if-let模式解构与??操作符帮助读者掌握在强类型、空安全语言中编写链表遍历类题解的完整实战方案。读完本文你应能独立用仓颉语言写出带进位传播的链表迭代算法并理解Option判空语法的真实语义。1. 题目与问题建模本题是 LeetCode 第 2 题「两数相加」Add Two Numbers。原题描述可在题目页面的官方链接readme 中给出的 leetcode.cn 题目链接此处按仓库规范不再重复外链中查看其核心规则为给定两个非空链表表示两个非负整数每个链表节点只存储一位数字且数字按逆序存储低位在链表头部假设两数都不含前导 0除数字 0 本身外将两个数相加以同样的逆序链表形式返回结果。逆序存储的设计使得链表头部恰好是低位天然契合「从低位到高位逐位相加、逐位进位」的十进制加法流程因此本题无需反转链表、无需整型转换用一次单向遍历即可完成。在 Exercises 仓库中该题解以独立子目录组织目录命名为「【Leetcode】2.两数相加」符合仓库根 README.md 中约定的提交规范每道编程题放在独立子目录、目录以题目命名并优先使用中文并在子目录放置readme.md填写题目描述与解题指导。目录内两个文件分工明确文件职责【Leetcode】2.两数相加/readme.md记录题目链接、解题思路、时间/空间复杂度与所用仓颉语法点【Leetcode】2.两数相加/n2.cj仓颉语言完整题解实现SolutionN2类共 41 行2. 解题思路三条件循环 逐位进位readme 中给出的核心思路原文为迭代两个 List只要满足l1不为 None、l2不为 None、进位不为 0 中条件之一就一直迭代 每次迭代sum l1 的值如果不为空 l2 的值如果不为空 进位。对应地源码 n2.cj#L24 中的循环条件写为while (l1cur.isSome() || l2cur.isSome() || carry ! 0) {这三个条件缺一不可逐条对应三类边界场景l1cur.isSome()l1 还有剩余位两链长度可能不等短链走完后长链仍需继续加l2cur.isSome()l2 还有剩余位carry ! 0两条链都耗尽后最高位可能仍有一次进位需要「额外追加一个节点」。例如 5 5 10链表遍历结束时carry仍为 1必须再多写一位。循环体内每一轮固定执行四步见 n2.cj#L25-L37sum初始化为carry上一轮的进位若 l1 当前节点存在则累加其val并把游标前移到node.next若 l2 当前节点存在做同样的累加与前移用整除与取模分离进位与当前位carry sum / 10、新节点值为sum % 10挂到结果链表尾部。3. 源码逐行剖析n2.cj以下是 n2.cj 的完整实现仅剔除头注释package cangjieLeetcode.n1_n100 import cangjieLeetcode.common.ListNode class SolutionN2 { func addTwoNumbers(l1: ?ListNode, l2: ?ListNode): ?ListNode { var t ListNode(0) var cur t var l1cur l1 var l2cur l2 var carry 0 while (l1cur.isSome() || l2cur.isSome() || carry ! 0) { var sum carry if(let Some(node) - l1cur) { sum node.val l1cur node.next } if(let Some(node) - l2cur) { sum node.val l2cur node.next } carry sum / 10 cur.next Some(ListNode(sum % 10)) cur cur.next??ListNode(0) } t.next } }3.1 哑头节点dummy head技巧第 19-20 行var t ListNode(0)、var cur t创建了值为 0 的哑头节点真正的结果节点从其next开始挂接。这样做的收益是结果链表始终非空无需对「第一个真实节点」做特判结束时直接返回t.next第 38 行天然剥离哑节点。由于返回值类型是?ListNode即OptionListNode且循环至少执行一次两个空链表输入不合法t.next在合法输入下必为Some因此可以直接作为Option返回。3.2if-let模式解构判空与取值的二合一第 26-33 行对两个游标分别使用了仓颉的if-let语法if(let Some(node) - l1cur) { sum node.val l1cur node.next }l1cur的类型是?ListNode可空类型。if(let Some(node) - l1cur)会在条件为真时把Option包裹的节点解构到局部变量node块内node即为非空的ListNode可直接访问node.val、node.next若游标已为None则整个if块被跳过。这避免了先isNone()判断、再手动取值的重复代码是仓颉处理可空类型的惯用写法。值得注意的是两个if块是独立的而非else if因为某轮循环中完全可能只有一条链还有剩余位两链长度不同必须各自独立判断、独立累加。3.3 进位与尾节点整除取模 ??兜底第 34-36 行carry sum / 10 cur.next Some(ListNode(sum % 10)) cur cur.next??ListNode(0)sum的取值范围是 0189 9 1 个进位故sum / 10只会得到 0 或 1sum % 10即当前位数字。这里利用了仓颉整型除法的整除语义每次循环都先给cur.next挂上新节点再把游标前移保证下一轮始终在结果链表尾部关于cur cur.next??ListNode(0)上一行刚执行过cur.next Some(...)因此从源码结构看cur.next在此处逻辑上必定是Some右侧的ListNode(0)兜底分支实际不会被构造——作者此处是在实践 readme 强调的??语法把「已知为 Some 的 Option」展开成值而非处理真实的空值分支。3.4 返回值循环结束后返回t.next。哑节点 0 被剔除若最后一轮产生了进位它已被第 3 个循环条件多跑一轮而追加为结果链表的最后一个节点如 999 1 的第三位 1。4. 仓颉语法点小结readme 的「仓颉语法」一节列出了本题涉及的两个知识点结合源码展开如下4.1Option的isSome()/isNone()?ListNode即OptionListNode可承载Some(node)或None两种状态。判断空值的谓词为isSome()/isNone()本题在while条件中连续使用了两个isSome()。4.2??操作符readme 原文描述Option类型的??语法a ?? b等同于if(a.isNone()){b} else {T}T 为 a 中包裹的值语义即左操作数为None时取右操作数作为默认值否则取出左操作数包裹的值。它等价于许多语言中的??nullish coalescing或 Swift/Kotlin 的??用法是提供兜底默认值最简练的写法。4.3 同系列题解中的关联用法同一包cangjieLeetcode.n1_n100下的其他题解展示了相近的 Option 用法可作交叉印证【Leetcode】1.两数之和/n1.cj 中if (let Some(x) - m.get(target - nums[i]))对HashMap.get的可空返回值做if-let解构与本题对链表游标的解构完全同构【Leetcode】3.无重复字符的最长子串/n3.cj 则展示了iterator()、enumerate()与扩展方法等其他仓颉特性。5. 一次完整的运行推演以经典样例l1 [2, 4, 3]表示 342、l2 [5, 6, 4]表示 465为例逐轮推演源码行为轮次进入时状态sum 计算新节点值 (sum % 10)carry出结果链尾节点1l1cur2, l2cur5, carry002577072l1cur4, l2cur6, carry004610017 - 03l1cur3, l2cur4, carry11348807 - 0 - 84l1curNone, l2curNone, carry0循环条件全部为假退出———返回t.next即7 - 0 - 8表示 807符合 342 465 807。再看进位溢出的边界样例l1 [9, 9, 9]、l2 [9, 9, 9, 9]前三轮分别得到 8/8/8 且 carry 恒为 1第四轮两条链中只剩 l2 的 9sum 1 9 10新节点 0、carry 仍为 1由于carry ! 0循环再跑第五轮sum 1追加节点 1 后 carry 归 0。最终结果为8 - 8 - 8 - 0 - 19999 999 10998恰好验证了第 2 节强调的第三个循环条件的必要性。6. 复杂度分析readme 给出的结论为时间 O(n)空间 O(1)。结合源码可以更精确地理解其口径时间设两链长度为 m、n循环轮数不超过max(m, n) 1多出的 1 轮用于消化最高位进位每轮 O(1)故时间复杂度为 O(max(m, n))即 readme 所述的 O(n)空间除输出结果链表本身外算法只使用cur、l1cur、l2cur、carry、sum等常数个变量辅助空间 O(1)。新建的结果节点是题目要求的返回值不计入辅助空间。7. 仓库内相关实现与阅读指引从源码结构看n2.cj顶部声明了package cangjieLeetcode.n1_n100并import cangjieLeetcode.common.ListNode而同目录的 n1、n3 题解共用同一个包名这说明本仓库中的 LeetCode 系列文件是按「同一外部工程模块」的约定组织的当前仓库内并未包含cangjieLeetcode.common包本身ListNode的定义不在本仓库提交范围内直接编译单个文件需要补上该公共依赖。如果想在仓库内寻找结构相近、可直接编译参考的ListNode实现可查看 算法思想解题合集/src/structures/listnode.cj它定义了带val: Int与next: ?ListNode None字段、多种构造器按值构造、按字符串1-5-3解析、按数组构造以及toString()打印链表的ListNode类其「字段 Option 型 next 便捷构造器」的设计与n2.cj所依赖的节点语义一致可作为理解链表节点建模的参考注意二者分属cj_algorithm.structures与cangjieLeetcode.common两个不同包并非同一类型。复现建议阅读本仓库时无需修改任何文件直接打开 n2.cj 对照本文第 3 节的逐行剖析即可若要在本地跑通建议按仓库根 README.md 的目录约定在具备仓颉开发环境含cjpm工具链的完整工程中添加cangjieLeetcode.common.ListNode公共定义再调用SolutionN2().addTwoNumbers(l1, l2)并打印返回链表验证第 5 节的推演结果。8. 小结本题的标准解法是哑头节点 双游标单向遍历循环条件l1cur.isSome() || l2cur.isSome() || carry ! 0完整覆盖了「长链剩余」「短链耗尽」「高位进位追加」三类边界仓颉侧的核心语言工具是Option判空isSome()/isNone()、if-let模式解构if(let Some(node) - opt)与??默认值操作符三者组合让空安全代码比显式判空写法更紧凑复杂度为时间 O(max(m, n))、辅助空间 O(1)是链表模拟题中「一次遍历、无回溯」的基准写法。赞分享示例工程教育【免费下载链接】Exercises本仓收集仓颉算法题解程序项目地址https://gitcode.com/Cangjie/Exercises点击查看免费下载相关推荐LeetCode 0002 Add Two Numbers 两数相加链表模拟竖式加法与进位传播实战解析含递归与迭代双解法LeetCode 0002 Add Two Numbers 两数相加链表模拟竖式加法与进位传播实战解析含递归与迭代双解法 本篇技术指南以 hints/ad示例工程教程AlgoNote 题解LeetCode 0002「两数相加」——逆序链表的竖式加法模拟与进位处理AlgoNote 题解LeetCode 0002「两数相加」——逆序链表的竖式加法模拟与进位处理 导读 本篇是「算法通关手册」AlgoNote 对 LeetC教程文档知识库LogicStack-LeetCode 题解精讲LeetCode 2. 两数相加——逆序链表竖式加法与哨兵技巧LogicStack LeetCode 题解精讲LeetCode 2. 两数相加——逆序链表竖式加法与哨兵技巧 本文是「刷穿 LeetCode」系列的第 2教程文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Max-Min公平性详解:从水填充算法到多用户带宽分配实践

Max-Min公平性详解:从水填充算法到多用户带宽分配实践

1. 资源分配里的"兜底哲学"做过多用户资源分配的工程师,大概都经历过这种争论:系统里有几个"大户"疯狂占用带宽,也有几个"小户"的需求一直得不到保障。老板拍板说"要公平",可什么是公平&…

2026/10/14 23:24:46 阅读更多 →
Claude Code 安装配置完全指南:从Node环境到终端AI编程助手

Claude Code 安装配置完全指南:从Node环境到终端AI编程助手

简介:面向开发者的Claude Code安装配置代码包,聚焦智能终端助手在Windows、macOS、Linux三平台下的部署与集成,帮助读者完成Node.js环境准备、全局安装、API密钥配置,并快速接入Visual Studio Code与JetBrains IDE。包体共3个文件…

2026/10/14 23:23:41 阅读更多 →
在线火山图绘制全攻略:从双色到四色的参数与实操

在线火山图绘制全攻略:从双色到四色的参数与实操

1. 先看懂火山图:坐标轴、阈值线、颜色的底层逻辑很多人上来就找按钮,先问“火山图在哪里”。我的建议是,先用两分钟理解这张图的坐标和阈值在说什么。你知道了每个参数背后的含义,在线工具里的选项就不会让你犯迷糊,出…

2026/10/14 23:23:41 阅读更多 →

最新新闻

手动部署OpenTelemetry Collector:从配置到运维的实践指南

手动部署OpenTelemetry Collector:从配置到运维的实践指南

简介:基于C#编写的winform Socket通信示例,面向需要掌握网络编程的C#初学者,演示了服务端与多个客户端同时连接与数据交互的实现过程。压缩包内包含服务端与客户端两个独立工程,可对照学习服务端监听、客户端连接以及多客户端并发…

2026/10/15 0:05:58 阅读更多 →
SpringBoot整合knife4j实战:接口文档与在线调试完整指南

SpringBoot整合knife4j实战:接口文档与在线调试完整指南

1. 为什么接口文档这件事值得单独拎出来聊做后端开发的人都有一个共识:写接口不难,难的是让前端、测试、甚至未来的自己看懂接口。早些年大家用 Swagger 那一套,ApiOperation、ApiModel注解满天飞,UI 长得像上世纪的产物&#xff…

2026/10/15 0:05:58 阅读更多 →
openrig 实战:用 tmux 与 Node.js 编排 Claude Code 和 Codex 多代理工作流

openrig 实战:用 tmux 与 Node.js 编排 Claude Code 和 Codex 多代理工作流

1. openrig 到底想解决什么问题第一次看到 openrig 这个名字,加上关联的 Claude Code、Codex、Node.js、tmux 这几个词,我脑子里冒出来的判断是:这大概率是一个把多个 AI 编码工具统一编排起来的工程化脚手架。后来实际折腾了一圈&#xff0c…

2026/10/15 0:04:56 阅读更多 →
AI入门避坑指南:零基础6个月可验证学习路线

AI入门避坑指南:零基础6个月可验证学习路线

1. 这不是“学AI”的路线图,而是帮你绕开99%初学者陷阱的生存指南你搜“人工智能入门”,页面刷出来全是“30天速成大模型”“零基础玩转ChatGPT”“PythonTensorFlow年薪30万”。我盯着屏幕看了三分钟,默默关掉网页——不是内容不好&#xff…

2026/10/15 0:04:56 阅读更多 →
探矿数据进RAG前的清洗全攻略:TXT、Word、PDF、网页四类文档处理实践

探矿数据进RAG前的清洗全攻略:TXT、Word、PDF、网页四类文档处理实践

1. 探矿数据进RAG之前,为什么必须先过清洗这一关1.1 探矿领域的文档生态:比想象中更杂做探矿业务的知识库和做通用知识库完全是两码事。通用场景里的文档再乱,基本也就是网页、PDF、Word这几类,格式相对规整。探矿业务呢&#xff…

2026/10/15 0:04:56 阅读更多 →
基于bbox的PDF文档解析:多栏重排与水印过滤实战

基于bbox的PDF文档解析:多栏重排与水印过滤实战

1. 项目概述:多栏和水印为什么是 RAG 解析里的两座山先说个场景。上个月我把一批技术论文和旧版产品手册塞进自建的 RAG 知识库,原以为 PDF 解析早就不是问题,结果检索结果让我怀疑人生:同一个问题的答案碎片化,有的片…

2026/10/15 0:04:56 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →