题目描述
给你两个非空链表,分别表示两个非负整数。表示方法:链表中的每个节点,分别表示整数中的一位数字,顺序从低位至高位。例如:2 -> 4 -> 3 表示342. 请计算两个整数的和,并返回成链表的形式。
数据保证两个整数均不包含前导0(除了0之外),例如:不会出现0023.
样例
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
解释:342 + 465 = 807.
算法
(模拟人工加法) $O(n)$
这是道模拟题,模拟我们小时候列竖式做加法的过程:
- 从最低位至最高位,逐位相加,如果和大于等于10,则保留个位数字,同时向前一位进1.
- 如果最高位有进位,则需在最前面补1.
做有关链表的题目,有个常用技巧:添加一个虚拟头结点:ListNode *head = new ListNode(-1);
,可以简化边界情况的判断。
时间复杂度:由于总共扫描一遍,所以时间复杂度是 $O(n)$.
C++ 代码
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
{
ListNode *res = new ListNode(-1); //添加虚拟头结点,简化边界情况的判断
ListNode *cur = res;
int carry = 0; //表示进位
while (l1 || l2)
{
int n1 = l1 ? l1->val : 0;
int n2 = l2 ? l2->val : 0;
int sum = n1 + n2 + carry;
carry = sum / 10;
cur->next = new ListNode(sum % 10);
cur = cur->next;
if (l1) l1 = l1->next;
if (l2) l2 = l2->next;
}
if (carry) cur->next = new ListNode(1); //如果最高位有进位,则需在最前面补1.
return res->next; //返回真正的头结点
}
};
此题样例有问题,无论样例是正相加还是逆相加都是807,
243+564=807
342+465=807
看来这道题目的样例设计得别有用心啊hh
这一行代码什么意思
l1 不是空节点,返回
l1
的值;是空节点,返回0简单写l1是可以判断它的指针域的吗?
可以,如果
l1
是空指针,l1
的值为 0,?
前面的bool是false。hhh明白了谢谢佬
请问创建一个虚拟头节点在哪里简化了边界判断呀
如果边界为空还要特判,但加上了头结点不论加完后的链表是否为空,返回形式都为res -> next
明白了谢谢!
y总,为什么跟你一样的代码,你用了9m空间,我用了60多m
LEETCODE 判定不准确
模拟题最喜欢考 模运算 和 除法运算的使用了 哈哈哈
为啥我一直是超出时间限制
l1
和l2
在指向next
的时候没赋值。求carry时,直接/10比较耗时, 建议用if else判断 sum - 10 >= 0
res->next是什么时候set到头节点的啊?程序执行完了cur不是指到最末了嘛,那最开始的cur = res会不会变?
res->next 自始至终表示头结点。
cur每次是在链表末尾加上一个新节点,第一次是在 res->next 的位置添加节点,这个点就是头结点。
问一下这道题follow up input list 不是reverse的话要怎么做哇?(除了先reverse之外。)
感觉除了先reverse一遍之外,没有其它办法了hh