给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
【解】
首先想到逆转链表然后相加更直观,但是不容易处理进位问题,发现逆序直接相加反而容易处理。只要遍历链表相加(记得处理进位问题)输出即可。大概这
链表1 | 2 | 3 | 5 | 1 | 4 |
链表2 | 3 | 2 | 9 |
解题过程中test case各种不通过,各种被吊打,感受一下:
test case暴露出来的问题:1)题干没有说两个链表不等长,一开始按两个链表长度相等来做,被test case吊打;2)最后两位相加要进位的问题没考虑,导致结果最后进位的数字丢失;3)各种NPE...... 4)没仔细审题,手残加了个链表逆序,其实题干并没有要求 - -+。
最后的结果跟上一题类似,依旧只击败了1/3的记录,显然常规操作效率并不高,说明还有优化的空间 :
优化:
原先的计算比较笨拙,遍历两个链表,然后新建一个链表保存结果,遍历需要各种判断边界和链表结束情况;
考虑一下可以直接在原有的一个链表上做累加操作,然后作为结果返回,遍历一次链表直到不再需要进位就可以结束,时间复杂度<=O(n);
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = l1;
ListNode joinPoint = null;
int carry = 0;
int value = 0;
while (l1!=null) {
value = l1.val + l2.val + carry;
if (value >= 10) {
carry = value / 10;
value = value % 10;
} else {
carry = 0;
}
l1.val = value;
joinPoint = l1;
if (l1.next == null) {
if (l2.next != null) {
l1.next = l2.next;
}
break;
}
if (l2.next == null) {
break;
}
l1 = l1.next;
l2 = l2.next;
}
while (carry > 0) {
if (null == joinPoint.next) {
joinPoint.next = new ListNode(carry);
carry = 0;
} else {
joinPoint.next.val = joinPoint.next.val + carry;
carry = joinPoint.next.val / 10;
joinPoint.next.val %= 10;
joinPoint = joinPoint.next;
}
}
// reverse list
// node = Reverse1(node);
return head;
}
执行结果: