题目描述
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
题目链接:https://leetcode-cn.com/problems/add-two-numbers/
思路
用链表来模拟人做加法,注意每一位的进位,以及最后是否有进位。最后如果有进位的话,则需要多加一个节点。代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if(l1==nullptr || l2==nullptr){
return nullptr;
}
int carry = 0; // 当前的进位
ListNode* head = new ListNode(0); // 新链表的链表头
ListNode* curNode = head;
while(l1!=nullptr && l2!=nullptr){
int s = l1->val+l2->val+carry;
ListNode* node = new ListNode(s%10);
carry = s/10;
curNode->next = node;
curNode = node;
l1 = l1->next;
l2 = l2->next;
}
if(l1==nullptr && l2!=nullptr){ //说明l1比较短,将l2剩余的部分加入到新链表当中
while(l2!=nullptr){
int s = l2->val+carry;
ListNode* node = new ListNode(s%10);
carry = s/10;
curNode->next = node;
curNode = node;
l2 = l2->next;
}
}
if(l1!=nullptr && l2==nullptr){ //说明l2比较短,将l1剩余的部分加入到新链表当中
while(l1!=nullptr){
int s = l1->val+carry;
ListNode* node = new ListNode(s%10);
carry = s/10;
curNode->next = node;
curNode = node;
l1 = l1->next;
}
}
if(l1==nullptr && l2==nullptr){ // 看最后有没有进位比如[1]+[9],有的话加上
if(carry!=0){ //有进位
ListNode* node = new ListNode(carry);
curNode->next = node;
}
}
return head->next;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(n)
链表所占的额外存储空间与输入的数据规模线性相关。
更简洁的代码
上面的代码可以写得更简洁,如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if(l1==nullptr || l2==nullptr){
return nullptr;
}
int carry = 0; // 当前的进位
ListNode* head = new ListNode(0);
ListNode* curNode = head;
while(l1!=nullptr || l2!=nullptr){
int x = l1==nullptr? 0:l1->val;
int y = l2==nullptr? 0:l2->val;
int s = x+y+carry;
ListNode* node = new ListNode(s%10);
curNode->next = node;
curNode = node;
carry = s/10;
if(l1!=nullptr) l1 = l1->next;
if(l2!=nullptr) l2 = l2->next;
}
if(carry!=0){
ListNode* node = new ListNode(carry);
curNode->next = node;
}
return head->next;
}
};
两种写法的时间空间复杂度是一样的。
总结
在模拟整数相加的时候,假设当前两个数相加为s,则s/10表示进位,s%10表示当前加的结果。