给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
ListNode是链表的一个节点结构体,通常在C++中用结构体来实现。
struct ListNode {
int val; // 节点的值
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 构造函数
};
其中val表示节点的值,next是指向节点的下一个节点的指针,为NULL表示该节点是最后一个节点。构造函数用于初始化节点的值和下一个节点的指针。
通过定义ListNode结构体,可以方便地创建一个链表。
例如:
ListNode* head = new ListNode(1); // 创建头结点
ListNode* p1 = new ListNode(2); // 创建第一个节点
ListNode* p2 = new ListNode(3); // 创建第二个节点
head->next = p1; // 头结点指向第一个节点
p1->next = p2; // 第一个节点指向第二个节点
#include
using namespace std;
//定义结构体
struct ListNode {
int val; //节点的值
ListNode* next; //指向下一个节点的指针
//构造函数用于初始化节点的值和下一个节点的指针
ListNode(int x) : val(x), next(NULL) {}; //构造函数,为空,表示该节点是最后一个节点。
ListNode(int x, ListNode* y) { val = x; next = y; }
};
int main()
{
//方法1
ListNode* head = new ListNode(1); //创建头节点
ListNode* p1 = new ListNode(2); //创建第一个节点
ListNode* p2 = new ListNode(3); //创建第二个节点
head->next = p1; // 头节点指向第一个节点
p1->next = p2; // 头节点指向第二个节点
//方法2
ListNode* pp = new ListNode(1, new ListNode(2, new ListNode(3)));
}
思路及算法:
1.两个链表都是逆序的,因此相同的位置可以直接相加;
2. 同时遍历两个链表,逐位进行相加,并与当前的进位进行相加;具体而言,如果当前位置相应的两个数分别位n1,n2,进位制为carry,那么当前的和的数值为n1 + n2 + carry;其中,答案链表处的数值为(n1 + n2 + carry)mod 10, 进位值为[(n1 + n2 + carry) / 10], 即取整;
3. 如果两个链表的长度不同,则短的后面位置可默认为0;
4. 如果链表遍历结束后,有carry >0 ,则还需在后面添加一个节点,节点值为carry。
#include
using namespace std;
//定义结构体
struct ListNode {
int val; //节点的值
ListNode* next; //指向下一个节点的指针
//构造函数用于初始化节点的值和下一个节点的指针
ListNode(int x) : val(x), next(NULL) {}; //构造函数,为空,表示该节点是最后一个节点。
ListNode(int x, ListNode* y) { val = x; next = y; }
};
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* head = nullptr, * tail = nullptr;
int carry = 0;
while (l1 || l2) {
int n1 = l1 ? l1->val : 0; //逐位读取,l1与l2谁短谁补零
int n2 = l2 ? l2->val : 0; //逐位读取
int sum = n1 + n2 + carry; //求和
if (!head) {
head = tail = new ListNode(sum % 10); //如果head为空,则首尾指向同一个值
}
else {
tail->next = new ListNode(sum % 10);
tail = tail->next;
}
carry = sum / 10; //计算当前进位值
if (l1) {
l1 = l1->next; //将剩余的next指向的数据赋给l1,相当于删除已经计算的节点
}
if (l2) {
l2 = l2->next; //将剩余的next指向的数据赋给l1
}
}
if (carry > 0) {
tail->next = new ListNode(carry); //如果carry>0,则需要额外添加一个节点
}
return head;
}
};
int main()
{
ListNode* head = new ListNode(1); //创建头节点
ListNode* p1 = new ListNode(2); //创建第一个节点
ListNode* p2 = new ListNode(3); //创建第二个节点
head->next = p1; // 头节点指向第一个节点
p1->next = p2; // 头节点指向第二个节点
ListNode* qhead = new ListNode(1); //创建头节点
ListNode* q1 = new ListNode(2); //创建第一个节点
ListNode* q2 = new ListNode(3); //创建第二个节点
qhead->next = q1; // 头节点指向第一个节点
q1->next = q2; // 头节点指向第二个节点
Solution solution;
solution.addTwoNumbers(head, qhead);
}
时间复杂度:O(max(m, n)),最长的节点的个数
空间复杂度:O(1),没有添加额外的空间,返回值不计入空间复杂度。