两数相加
题目链接: 两数相加
题目描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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
题目数据保证列表表示的数字不含前导零
方法一
思路
1.将链表进行反转
2.将翻转后的链表转换为数字
3.相加之后再存入链表中
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
// 链表翻转
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* cur = head;
ListNode* nep = nullptr;
while (cur != nullptr) {
nep = cur->next;
cur->next = prev;
prev = cur;
cur = nep;
}
return prev;
}
// 链表转数字
long long listToNum(ListNode* head) {
ListNode* p = head;
long long num = 0;
while (p != nullptr) {
num = num * 10 + p->val;
p = p->next;
}
return num;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* reverseL1 = reverseList(l1);
ListNode* reverseL2 = reverseList(l2);
ListNode *p1 = reverseL1, *p2 = reverseL2;
long long num1 = listToNum(p1);
long long num2 = listToNum(p2);
long long sum = num1 + num2;
int ini = sum % 10;
sum /= 10;
ListNode* head = new ListNode(ini);
ListNode* p = head;
// 倒序生成链表
while (sum != 0) {
int ge = sum % 10;
sum = sum / 10;
p->next = new ListNode(ge);
p = p->next;
}
return head;
}
};
存在的问题:测试用例通过1565 / 1568
,最后几个是因为整数超范围导致了栈溢出,因此这种方法不能100%跑通
方法二
参考官方题解
1.对应位置上的数可以直接相加,所以可以直接遍历链表,对应位置相加
2.相加时考虑到进位问题,所以要设置一个进位carry
存储进位值,而这个进位值等于num/10
,往节点里存的值等于num%10
3.当短的链表加完之后,将剩余的值与0相加
4.最后都结束之后,判断进位标志carry
是否大于0,如果大于0,就放在链表最后。
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
/** 分析:
两个链表中同一个位置的可以直接相加,使用一个标记为flag标记进位,
也就是比如9+9=18,将个位存储在节点,十位记为进位位
*/
ListNode* p1 = l1;
ListNode* p2 = l2;
ListNode* head = nullptr;
ListNode* p = nullptr;
int carry = 0;
while (p1 != nullptr || p2 != nullptr) {
int n1 = p1 ? p1->val : 0;
int n2 = p2 ? p2->val : 0;
int num = n1 + n2 + carry;
carry = num / 10;
// 将num放入节点
if (!head) {
head = p = new ListNode(num % 10);
} else {
p->next = new ListNode(num % 10);
p = p->next;
}
if (p1) {
p1 = p1->next;
}
if (p2) {
p2 = p2->next;
}
}
if (carry > 0) {
p->next = new ListNode(carry);
}
return head;
}
};