leetcode(2) —— 两数相加
2019年9月12日 · 189 字 · 1 分钟
本文是力扣算法的第二篇,讲解两数相加问题。
Question
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
分析
遍历两个链表把值加起来好之后插入链表,如果有进位的话需要把进位的值保存到后面的节点上,如果遍历完毕之后还剩下需要进位的值,那么需要插入末尾新节点。
边界情况
遇到链表相关的题目时一定要处理好边界情况,因为有些为空的链表或者只有1个节点的链表没有处理的必要,及时返回可以降低算法复杂度。
- 链表1和链表2同时为空,直接返回undefined即可
- 链表1为空,返回链表2
- 链表2为空,返回链表1
解题方法
// 链表节点定义
function ListNode(val) {
this.val = val;
this.next = null;
}
function addTwoNumbers(l1, l2) {
if(!l1 && !l2) { // 链表1和链表2同时为空,无需任何处理
return;
}
if(!l1) { // 链表1为空,直接返回链表2
return l2;
}
if(!l2) { // 链表2为空,直接返回链表1
return l1;
}
let carry = 0; // 进位值
let head = new ListNode(0); // 链表头节点
let p = head; // 链表移动指针
while(l1 || l2 || carry > 0) { // l1和l2虽然不会同时为空,但是存在l1和l2长度不一致的情况, 这种也需要处理
let sum = carry; // sum为本节点的值,需要加上前一个节点的进位值
if(l1) {
sum += l1.val; // 把链表1当前节点的值加上
l1 = l1.next; // 移动链表1指针
}
if(l2) {
sum += l2.val;
l2 = l2.next;
}
if(sum >= 10) { // 两个个位数相加最大值为18,所以到下一个节点进位的最大值为1
carry = 1;
sum -= 10; // 去掉十位,保留个位为节点最终值
} else {
carry = 0; // 相加之后和小于10,不需要进位,清除进位数据,否则死循环
}
p.next = new ListNode(sum); // 插入新节点
p = p.next; // 新链表指针后移
}
return head.next; // 头结点的值不是相加得到的,所以需要后移一个节点返回由两个链表加起来的结果
}
进位的处理搞清楚之后这道题就清楚了。
时间复杂度O(max(l1.length, l2.length))
循环次数的根据链表1和链表2中长的那个链表来的,因为要保证两个链表的所有节点都被便利到
空间复杂度O(max(l1,l2))
最终链表的节点数也是根据链表1和链表2中长的那个链表来的,因为要保证两个链表的所有节点都被便利到,如果最后有进位的话,结果链表的长度会比链表1和链表2中长的链表大小+1。
结尾
这道题的难度是中等,但是摸清楚链表的基本操作之后,应该没什么问题就能解决。