letcode 2.两数相加(官方题解笔记)
创始人
2025-05-29 10:02:46
0

题目描述

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

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

除数字 0 之外,这两个数都不会以 0 开头。

1.模拟(加法器)

1.1思路

时间复杂度:O( max(m ,n) )
空间复杂度:O(1)

笔者疑惑:官方给出的程序中,答案链表所占空间大小应为 max(m,n)max(m,n) + 1,所以此处笔者觉得该算法空间复杂度应为 O(max(m,n)),求解惑。

由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加。

我们同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。
具体而言,如果当前两个链表处相应位置的数字为 n1n2,进位值为 carry,则它们的和为 n1 + n2 +carry
其中,答案链表处相应位置的数字为 (n1 + n2 + carry) mod 10,而新的进位值为 ⌊(n1 + n2 + carry) / 10⌋

如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0

此外,如果链表遍历结束后,有 carry > 0,还需要在答案链表的后面附加一个节点,节点的值为 carry

1.2代码

1.C

// 注:前面应该还有定义链表结构体的步骤
// l1:链表1,l2:链表2
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {struct ListNode *head = NULL, *tail = NULL;	// 答案链表的头 [head] 尾 [tail] 结点int carry = 0;	// 加法进位while (l1 || l2) {	// l1 和 l2 只要有一个没有遍历结束就一直执行此循环int n1 = l1 ? l1->val : 0;	// n1 记录 l1 当前结点的数字,若为空则置0,否则置 l1 当前结点的值int n2 = l2 ? l2->val : 0;	// n2 记录 l2 当前结点的数字,若为空则置0,否则置 l2 当前结点的值int sum = n1 + n2 + carry;	// 相同位置之和 sum = 两链表相同位置的结点的值相加再加上仅为 carry// 下面的 if - else 语句用于将对应位置相加的值插入答案链表,因原链表为逆序,故使用尾插法if (!head) {	// 头结点为空head = tail = malloc(sizeof(struct ListNode));	// 为新结点申请空间tail->val = sum % 10;	// 尾插对应目标值tail->next = NULL;} else {	// 头结点不为空tail->next = malloc(sizeof(struct ListNode));	// 为新结点申请空间tail->next->val = sum % 10;	// 尾插对应目标值tail = tail->next;tail->next = NULL;}carry = sum / 10;	// 计算进位值 carry = ⌊(n1 + n2 + carry) / 10⌋if (l1) {	// l1 不为空,遍历 l1 的下一个结点l1 = l1->next;}if (l2) {	// l2 不为空,遍历 l2 的下一个结点l2 = l2->next;}}if (carry > 0) {	// 遍历结束后 carry > 0,则额外申请一个新结点存放 carrytail->next = malloc(sizeof(struct ListNode));tail->next->val = carry;tail->next->next = NULL;}return head;	// 返回答案链表的头结点
}

2.C++

class Solution {
public:// 注:前面应该还有定义链表结构体的步骤// l1:链表1,l2:链表2ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {// nullptr 用于避免指针赋空值容易出现的二义性问题,其本质相当于 NULLListNode *head = nullptr, *tail = nullptr;	// 答案链表的头 [head] 尾 [tail] 结点int carry = 0;	// 加法进位while (l1 || l2) {	// l1 和 l2 只要有一个没有遍历结束就一直执行此循环int n1 = l1 ? l1->val: 0;	// n1 记录 l1 当前结点的数字,若为空则置0,否则置 l1 当前结点的值int n2 = l2 ? l2->val: 0;	// n2 记录 l2 当前结点的数字,若为空则置0,否则置 l2 当前结点的值int sum = n1 + n2 + carry;	// 相同位置之和 sum = 两链表相同位置的结点的值相加再加上仅为 carry// 下面的 if - else 语句用于将对应位置相加的值插入答案链表,因原链表为逆序,故使用尾插法if (!head) {	// 头结点为空head = tail = new ListNode(sum % 10);	// 为新结点申请空间,尾插入对应目标值} else {	// 头结点不为空tail->next = new ListNode(sum % 10);	// 为新结点申请空间,尾插入对应目标值tail = tail->next;}carry = sum / 10;	// 计算进位值 carry = ⌊(n1 + n2 + carry) / 10⌋if (l1) {	// l1 不为空,遍历 l1 的下一个结点l1 = l1->next;}if (l2) {	// l2 不为空,遍历 l2 的下一个结点l2 = l2->next;}}if (carry > 0) {	// 遍历结束后 carry > 0,则额外申请一个新结点存放 carrytail->next = new ListNode(carry);}return head;	// 返回答案链表的头结点}
};

3.Java

class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode head = null, tail = null;int carry = 0;while (l1 != null || l2 != null) {int n1 = l1 != null ? l1.val : 0;int n2 = l2 != null ? l2.val : 0;int sum = n1 + n2 + carry;if (head == null) {head = tail = new ListNode(sum % 10);} else {tail.next = new ListNode(sum % 10);tail = tail.next;}carry = sum / 10;if (l1 != null) {l1 = l1.next;}if (l2 != null) {l2 = l2.next;}}if (carry > 0) {tail.next = new ListNode(carry);}return head;}
}

4.C#

public class Solution {public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {ListNode head = null, tail = null;int carry = 0;while (l1 != null || l2 != null) {int n1 = l1 != null ? l1.val : 0;int n2 = l2 != null ? l2.val : 0;int sum = n1 + n2 + carry;if (head == null) {head = tail = new ListNode(sum % 10);} else {tail.next = new ListNode(sum % 10);tail = tail.next;}carry = sum / 10;if (l1 != null) {l1 = l1.next;}if (l2 != null) {l2 = l2.next;}}if (carry > 0) {tail.next = new ListNode(carry);}return head;}
}

5.Javascript

var addTwoNumbers = function(l1, l2) {let head = null, tail = null;let carry = 0;while (l1 || l2) {const n1 = l1 ? l1.val : 0;const n2 = l2 ? l2.val : 0;const sum = n1 + n2 + carry;if (!head) {head = tail = new ListNode(sum % 10);} else {tail.next = new ListNode(sum % 10);tail = tail.next;}carry = Math.floor(sum / 10);if (l1) {l1 = l1.next;}if (l2) {l2 = l2.next;}}if (carry > 0) {tail.next = new ListNode(carry);}return head;
};

6.Golang

func addTwoNumbers(l1, l2 *ListNode) (head *ListNode) {var tail *ListNodecarry := 0for l1 != nil || l2 != nil {n1, n2 := 0, 0if l1 != nil {n1 = l1.Vall1 = l1.Next}if l2 != nil {n2 = l2.Vall2 = l2.Next}sum := n1 + n2 + carrysum, carry = sum%10, sum/10if head == nil {head = &ListNode{Val: sum}tail = head} else {tail.Next = &ListNode{Val: sum}tail = tail.Next}}if carry > 0 {tail.Next = &ListNode{Val: carry}}return
}

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...