数据结构与算法之链表: LeetCode 2. 两数相加 (Ts, Py, Go版)

2025ICPC南昌邀请赛题解 2025ICPC南昌邀请赛由XDU和WHU联合出题的ICPC南昌邀请赛,榜单显示8题金、6题银、5题铜。 阅读详情

两数相加

  • https://leetcode.cn/problems/add-two-numbers/

描述

  • 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

  • 请你将两个数相加,并以相同形式返回一个表示和的链表。

  • 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

Typescript 版算法实现

1 )方案 1

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function addTwoNumbers(l1: ListNode | null, l2: ListNode | null): ListNode | null {
    const l3 = new ListNode(0); // 初始化l3链表,空链表
    // 通过指针遍历链表,声明各个指针
    let p1 = l1; // p1指向第一个链表的头部
    let p2 = l2; // 同上
    let p3 = l3; // 同上
    let carry = 0; // 十位数上的数

    // 两个链表中都没有遍历完成都可以继续执行
    while(p1 || p2) {
        const v1 = p1 ? p1.val : 0; // 拿到p1指针的值
        const v2 = p2 ? p2.val : 0; // 拿到p2指针的值
        // 对两个链表的值进行计算
        const val = v1 + v2 + carry; // 比如 2+5, 4+6
        // 下面两行是核心
        carry = Math.floor(val / 10); // 拿到进位,以便下位进行相加(下一轮)
        p3.next = new ListNode(val % 10); // 处理新链表的next
        // 把所有指针往后移动一位
        p1 && (p1 = p1.next);
        p2 && (p2 = p2.next);
        p3 = p3.next; // p3永远有值
    }
    // 循环结束后,判断是否有进位,有则处理进位
    carry && (p3.next = new ListNode(carry));
    return l3.next; // 因为l3初始的时候是一个临时的初始值,所以返回它的next
};
  • 解题思路

    • 小学数学题,模拟相加操作
    • 从个位开始相加
    • 执行相加逻辑,需要遍历链表
  • 解题步骤

    • 新建一个空链表
    • 遍历被相加的两个链表,模拟相加操作,将个位数追加到新链表上,将十位数留到下一位去相加
    • 因为都是一位数字,每个节点存储的数字都是个位数,十位数是是两个链表对应节点数字相加产生的进位
    • 链表遍历完,新链表也构建完成

2 )方案2

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

function addTwoNumbers(l1: ListNode | null, l2: ListNode | null): ListNode | null {
    // 链表边界条件判断,特殊情况可提前结束程序
    if (l1 === null && l2 === null) {
        return null;
    } else if (l1 === null) {
        return l2;
    } else if (l2 === null) {
        return l1;
    }
    let head = null, tail = null
    let carry = 0;
    while (l1 || l2) {
        const val1 = l1 ? l1.val : 0;
        const val2 = l2 ? l2.val : 0;
        const sum = val1 + val2 + carry;
        if (!head) {
            head = tail = new ListNode(sum % 10)
        } else {
            tail.next = new ListNode(sum % 10)
            tail = tail.next
        }
        carry = Math.floor(sum / 10);
        l1 = l1 && l1.next;
        l2 = l2 && l2.next;
    }
    if (carry) {
        tail.next = new ListNode(carry)
    }
    return head;
};
  • 上述是官方示例程序,类似的思想

Python3 版算法实现

1 )方案1

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        l3 = ListNode(0)  # 初始化l3链表,空链表  
        # 声明各个指针  
        p1 = l1  # p1指向第一个链表的头部  
        p2 = l2  # p2指向第二个链表的头部  
        p3 = l3  # p3指向结果链表的当前节点  
        carry = 0  # 十位数上的数  
    
        # 当两个链表中有任意一个未遍历完时,继续循环  
        while p1 or p2:  
            v1 = p1.val if p1 else 0  # 拿到p1指针的值
            v2 = p2.val if p2 else 0  # 拿到p2指针的值
            # 对两个链表的值进行计算  
            val = v1 + v2 + carry  # 计算当前位的和  
            # 更新进位和当前位的值  
            carry = val // 10  # 获取进位  
            p3.next = ListNode(val % 10)  # 创建新节点保存当前位的值  
            # 将指针向后移动一位  
            p1 = p1.next if p1 else None  
            p2 = p2.next if p2 else None  
            p3 = p3.next  # 移动结果链表的指针  
    
        # 如果循环结束后还有进位,需要添加新节点保存进位  
        if carry:  
            p3.next = ListNode(carry)  
    
        # 返回结果链表的下一个节点(跳过初始化时的临时节点)  
        return l3.next  
    
    # 注意:在Python中,链表节点通常是通过实例化ListNode类来创建的
    # 并且链表的尾部通常是通过将新节点的next指向None来结束
    # 当传递链表给函数时,确保链表的尾部节点的next属性为None

2 )方案2

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        # 链表边界条件判断,特殊情况可提前结束程序  
        if not l1:  
            return l2  
        elif not l2:  
            return l1  
        
        # 初始化头尾节点和进位  
        head = tail = ListNode(0)  
        carry = 0  
        
        # 遍历链表  
        while l1 or l2:  
            val1 = l1.val if l1 else 0  
            val2 = l2.val if l2 else 0  
            total = val1 + val2 + carry  
            
            # 创建新节点并更新头尾指针  
            if not head:  
                head = tail = ListNode(total % 10)  
            else:  
                tail.next = ListNode(total % 10)  
                tail = tail.next  
            
            # 更新进位  
            carry = total // 10  
            
            # 移动链表指针  
            l1 = l1.next if l1 else None  
            l2 = l2.next if l2 else None  
        
        # 检查是否还有进位需要处理  
        if carry:  
            tail.next = ListNode(carry)  
        
        # 返回头节点  
        return head.next  # 跳过初始化的哑节点  
    
    # 注意:在Python中,链表节点通常是通过实例化ListNode类来创建的,  
    # 并且链表的尾部通常是通过将新节点的next指向None来结束。  
    # 当传递链表给函数时,确保链表的尾部节点的next属性为None。

Golang 版算法实现

1 )方案1

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

// 实现链表相加函数  
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	// 初始化l3链表,哑节点  
	dummy := &ListNode{}  
	current := dummy  
	carry := 0 // 进位  
  
	// 通过指针遍历链表  
	for l1 != nil || l2 != nil {  
		var x, y int  
		if l1 != nil {  
			x = l1.Val  
			l1 = l1.Next  
		} else {
			x = 0
		}
		if l2 != nil {
			y = l2.Val
			l2 = l2.Next
		} else {  
			y = 0  
		}  
  
		// 计算当前位的和以及进位  
		sum := x + y + carry  
		carry = sum / 10  
		digit := sum % 10  
  
		// 创建新节点并添加到l3链表中  
		current.Next = &ListNode{Val: digit}  
		current = current.Next  
	}  
  
	// 如果最后还有进位,添加到l3链表尾部  
	if carry > 0 {  
		current.Next = &ListNode{Val: carry}  
	}  
  
	// 返回l3链表的下一个节点(跳过哑节点)  
	return dummy.Next  
}

2 ) 方案2

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */

// 实现链表相加函数
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {  
	// 链表边界条件判断,特殊情况可提前结束程序  
	if l1 == nil && l2 == nil {  
		return nil  
	} else if l1 == nil {  
		return l2  
	} else if l2 == nil {  
		return l1  
	}  
  
	var head, tail *ListNode  
	carry := 0  
  
	for l1 != nil || l2 != nil {  
		var val1, val2 int  
		if l1 != nil {  
			val1 = l1.Val  
			l1 = l1.Next  
		} else {  
			val1 = 0  
		}  
		if l2 != nil {  
			val2 = l2.Val  
			l2 = l2.Next  
		} else {  
			val2 = 0  
		}  
  
		sum := val1 + val2 + carry  
		if head == nil {  
			head = &ListNode{Val: sum % 10}  
			tail = head  
		} else {  
			tail.Next = &ListNode{Val: sum % 10}  
			tail = tail.Next  
		}  
  
		carry = sum / 10  
	}  
	if carry > 0 {  
		tail.Next = &ListNode{Val: carry}  
	}  
	return head
}
Android Audio音量——音频类型新增(九) 在实际开发中,经常会遇到需要新增一个音频类型(usage)的需求,这里我们简单介绍一下需要修改的代码。 阅读详情

相关推荐

5G协议栈逆向工程:基于开源模拟器的核心网信令分析实战

本文详细介绍了基于开源模拟器Free5GC和UERANSIM的5G协议栈逆向工程实战,涵盖核心网信令分析、环境搭建、认证协议解析及安全漏洞验证。通过NGAP/NAS信令交互解密和异常流量注入测试,帮助研究人员深入理解5G网络安全机制,并提供实用的安全加固建议。

weixin_29250573的博客 678

【码上学前端】TS 两数之和

本文介绍了一种使用哈希表解决两数之和问题的算法,该算法的时间复杂度为 O(n),空间复杂度为 O(n)。同时,本文还详细解释了哈希表的原理和使用方法,以及该算法的优缺点和实现细节。在实际应用中,哈希表是一种非常常用的数据结构,具有快速查找和插入的特点,可以用于解决多种问题。

码小余の博客 930

软件工程实验报告--用Visio绘制数据流图、ER图、状态图、软件结构图、程序流程图、系统流程图

用Visio绘制数据流图、ER图、状态图、软件结构图、程序流程图、系统流程图

m0_73814332的博客 4168

js解决两个数相加的问题

我需要得到js实现两个数字相加的结果,可是js总是默认按照字符串处理,将两个数字连接起来。 解决这个问题,代码如下:<script type="text/javascript"> var a = 1; var b = 2; var sum = parseInt(a) + parseInt(b); </script>parseInt()是js的解析字符串的函数,返回解析后的数

Mark技术之家 2万+

STM32入门教程:智能马桶盖控制

通过编写相应的代码,您可以根据需要实现其他功能,例如座圈温度调节和液晶显示屏显示等。初始化配置 首先,使用STM32CubeMX创建一个新的工程,并选择您所使用的STM32单片机型号。智能马桶盖是一种集成了多种功能的智能家居设备,通过控制芯片来实现自动冲水、座圈加热、座圈温度调节等功能。在本教程中,我们将使用STM32系列单片机来控制智能马桶盖的各个功能。以上代码演示了如何通过STM32的GPIO控制引脚来控制智能马桶盖的冲水和座圈加热功能。写代码 接下来,我们将通过编写代码来控制智能马桶盖的各个功能。

2401_85258012的博客 658

AIGC算法工程师面试八股文深度解析与进阶指南:揭秘Diffusion Models核心原理与实战技巧

总结来说,Cosine Noise Scheduler 的核心优势在于它能够更巧妙地平衡信号和噪声的比例,在扩散过程的早期阶段更长时间地保留原始图像的细节信息,从而为去噪模型提供一个更友好的学习环境,最终带来更优异的生成质量。🚀

FJN110的博客 346

数据结构与算法之链表: LeetCode 237. 删除链表中的节点 (Ts, Py, Go版)

链表的所有值都是 唯一的,并且保证给定的节点 node 不是链表中的最后一个节点。给你一个需要删除的节点 node。你将 无法访问 第一个节点 head。注意,删除节点并不是指从内存中删除它。有一个单链表的 head,我们想删除它其中的一个节点 node。

Wang的专栏 666

新手必读!2025最全AI智能体入门手册,50个问题全讲透

感知(Perception):能读取环境,比如读取网页数据、识别用户输入、接入 API;思考(Reasoning/Planning):理解任务目标,规划出行动步骤;行动(Action):调工具、查资料、发消息、写入数据库……直接执行任务。有了这三步,智能体才不是“一个会说话的大模型”,而是真正的“能落地执行的工作代理人”。多个 Agent 分工协作,每个智能体负责一个角色或任务节点,像一个“虚拟团队”。一个爬数据的 Agent,一个提炼要点的 Agent,一个撰写报告的 Agent,

互联网架构师笔记 1973

数据结构与算法之链表: LeetCode 148. 排序链表 (Ts, Py, Go版)

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表

Wang的专栏 967

科研神器: 用Gemini 3

Edge藏了个科研开挂神器!免TZ/免谷歌账号用Gemini 3,1分钟上手(附保姆级教程) 做科研查文献、理数据总卡壳?想蹭Gemini 3的AI能力,却被“谷歌账号+TZ+节点筛选”三连劝退? 现在不用折腾了!Edge浏览器里装个插件,直接把Gemini 3揣进口袋——**免翻墙、免谷歌账号、国内直接用**,分分钟让你的科研效率翻三倍,导师都得问你“偷偷开了啥挂”!

ZhangJiqun&191cm&85kg 1161

PCL 贪婪投影三角剖分算法【2025最新版】

本博客在学习PCL中的贪婪投影三角算法的基础上,实现了使用彩色点云重建彩色模型的应用案例。博客长期更新,最近一次更新时间为:2025年7月6日。

点云侠的博客 37万+

数据结构与算法之链表: LeetCode 141. 环形链表 (Ts, Py, Go版)

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回 true。否则,返回 false。给你一个链表的头节点 head ,判断链表中是否有环。

Wang的专栏 682

基于A*算法的二维栅格地图路径规划与避障MATLAB仿真

本文将介绍如何使用MATLAB编写基于A*算法的二维栅格地图路径规划与避障的仿真程序。我们可以使用二维数组表示地图,其中每个元素表示一个栅格的状态,例如1表示障碍物,0表示可行走区域。接下来,我们需要定义A*算法的节点类。G值表示从起始节点到当前节点的代价,H值是启发式函数估计的从当前节点到目标节点的代价。算法,我们可以有效地找到起始点到目标点的最短路径,并在仿真中进行可视化展示。算法的基本思路是从起始节点开始,按照一定的启发式函数选择下一个节点,直到找到目标节点或者遍历完所有可行走区域。

ByteWhizX的博客 1275

数据结构与算法之链表: LeetCode 206. 反转链表 (Ts, Py, Go版)

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

Wang的专栏 298

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

数据结构与算法之链表: LeetCode 83. 删除排序链表中的重复元素 (Ts, Py, Go版)

【代码】数据结构与算法之链表: LeetCode 83. 删除排序链表中的重复元素 (Ts, Py, Go版)

Wang的专栏 667

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

数据结构与算法之堆: LeetCode 23. 合并K个升序链表 (Ts, Py, Go版)

LeetCode 23. 合并K个升序链表 (Ts, Py, Go版)

Wang的专栏 351

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

数据结构与算法之排序: LeetCode 21. 合并两个有序链表 (Ts, Py, Go版)

1 )遍历两个链表,依次比较存入结果链表。2 )递归

Wang的专栏 530

Fish Audio Drama 3 部署指南:多说话人 TTS 从权重拉取到高并发上线

Fish Audio Drama 3 是面向多角色剧情、有声剧与长文本配音的多说话人 TTS(文本转语音)模型,本文带你从零走通一次完整的 Drama 3 部署。它的核心卖点是:16 个说话人同台、参考音频即可克隆音色、长文本自动分块并流式输出,单卡 H200 上 64 并发仍能快于实时。读完你能独立装好 SGLang-Omni 推理框架、拉取约 39.6 GB 的权重、在单卡上起服务并发出第一个

gitblog_00977的博客 888

Brush 安装教程:桌面端 2 条命令跑通高斯泼溅 3D 重建

Brush 是基于高斯泼溅(Gaussian Splatting)的开源 3D 重建引擎:喂一组照片,它训练出可实时漫游的 3D 场景。这篇 Brush 安装教程覆盖桌面、浏览器、Android 三条路径,跟做完你多出一个能边训边看、可交互漫游的 3D 查看器。 ## 开工前对照:各平台 Brush 安装依赖速查 | 平台/依赖 | 最低要求 | 备注 | | --- | --- | ---

gitblog_00842的博客 1046

数据结构与算法之队列: LeetCode 622. 设计循环队列 (Ts, Py, Go版)

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。设计你的循环队列实现。循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

Wang的专栏 719

LeetCode 1. 两数之和(Two Sum)题解:哈希表单趟扫描的 O(n) 解法与 15 种语言实现

> 本文基于 doocs/leetcode 仓库中 [1. Two Sum 题解文档](https://link.gitcode.com/i/f30dc54976b7587ff07ee0f3c8b1aeaf)(含 [中文版](https://link.gitcode.com/i/531dccf9fc99ceb794d86b5221eb207e))展开,以哈希表解法为核心,完整呈现题目约束、算法推导

gitblog_00781的博客 797

LeetCode 0002 Add Two Numbers 两数相加:链表模拟竖式加法与进位传播实战解析(含递归与迭代双解法)

本篇技术指南以 [hints/add-two-numbers.md](https://link.gitcode.com/i/d09e9732627ed1e3b6fd046ab49f757a) 的解题提示为核心骨架,结合 [articles/add-two-numbers.md](https://link.gitcode.com/i/c4a1aac252515dd892fef5aee3659d95)

gitblog_00868的博客 136

LeetCode 142 环形链表 II 题解:Floyd 判圈算法如何 O(1) 空间定位环的入口节点

本文基于 doocs/leetcode 仓库中 [142. 环形链表 II](https://link.gitcode.com/i/9aa3fa873016c83d18c15dffb447e2c6) 的完整题解展开,系统讲解如何利用快慢指针(Floyd 判圈算法)在 `O(n)` 时间、`O(1)` 空间内找到链表开始入环的第一个节点,并完整给出该算法背后的数学推导过程与 Python、Java、

gitblog_01009的博客 458

PX4无人机集群控制实战:3个机制+5步验证,从多机仿真跑到真机集群

三架无人机同时起飞,地面站却开始"串台":姿态流错发给了2号机,3号机的心跳隔几秒才到一次。这类PX4集群控制问题,十有八九出在标识和端口上,而不是算法。下面我们不讲概念,直接从跑通一次PX4 SITL多实例(软件在环的多机仿真)开始,一路拆到真机。 ## 🚁 先跑起来:多机仿真环境一键搭建 单机能飞,集群就会卡在这一步:你以为启动了3个进程,其实3个进程在用同一套端口和同一个系统ID。

gitblog_00775的博客 402

剑指 Offer II 022 链表中环的入口节点:快慢指针与 Floyd 判圈算法深度解析(doocs/leetcode)

本文围绕 doocs/leetcode 仓库中《剑指 Offer(第 2 版)》的 [lcof2/剑指 Offer II 022. 链表中环的入口节点](https://link.gitcode.com/i/84aab194df181d2be42672aaeae09ba2) 展开,系统讲解如何在只遍历链表、不修改链表的前提下,用 O(1) 空间定位环的入口节点。读完本文,你将掌握 Floyd 判圈

gitblog_00869的博客 191

LeetCode 61. 旋转链表(Rotate List)题解:快慢指针与链表拼接的 O(1) 空间实现

本篇技术指南以 doocs/leetcode 仓库中 [61. Rotate List 题解文档](https://link.gitcode.com/i/7f5172f7639415f286d1cd971696d32f) 为骨架,完整讲解「旋转链表」这道中等难度链表题的题目约束、核心思路、算法流程与复杂度,并逐语言展开 Python3、Java、C++、Go、TypeScript、Rust、C#

gitblog_00487的博客 383
上一篇: 数据结构与算法之链表: LeetCode 206. 反转链表 (Ts, Py, Go版)
下一篇: 数据结构与算法之链表: LeetCode 83. 删除排序链表中的重复元素 (Ts, Py, Go版)
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值