Problem 02. add-two-numbers
题目描述
-
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按逆序的方式存储的,并且它们的每一个节点只能存储一位数字。
-
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
-
可以假设除了0之外,这两个数都不会以0开头。
-
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
解题思路
-
看完题目,最初的想法就是先把链表中的数据取出来,分别转换成对应整数,将两个整数相加后再转换到链表中。写完代码后运行了一下,居然是错的???才发现链表中的整数是逆序存储的(审题!审题!)。逆序就逆序,那我就先把两个整数翻转一下,相加后再翻转,然后放进链表里不就行了?实现是实现了,不过不知道为啥一直有bug,可是我觉得思路没错啊。。。(后面有时间再来研究一下到底哪里有问题。。)
-
感觉上面的思路太繁琐,实现起来也麻烦。还是直接在两个链表上进行加法操作吧(这应该是这道题目的初衷,因为它在链表中逆序存储,两个链表头就是对齐的,就像我们列竖式计算时从个位开始对齐)。那么我们就从链表l1和l2的表头开始进行加法运算,将对应位置的两个数字进行加和,然后判断是否有进位的情况。设置一个 carry 来存储进位的情况,假设某两位数字的和为 sum ,那么 carry = sum / 10 ,且本位的和应该为 sum / 10 。以此进行迭代,直至两个链表都遍历完成,要注意的是,循环完成之后还要判断一次 carry 是否还有进位。代码实现如下:
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode resultHead = new ListNode(0);
ListNode p1 = l1, p2 = l2, current = resultHead;
int carry = 0;
while(p1 != null || p2 != null) {
int a = p1 != null ? p1.val : 0;
int b = p2 != null ? p2.val : 0;
int sum = a + b + carry;
carry = sum / 10;
current.next = new ListNode(sum % 10);
current = current.next;
if(p1 != null) {
p1 = p1.next;
}
if(p2 != null) {
p2 = p2.next;
}
}
if(carry > 0) {
current.next = new ListNode(carry);
}
return resultHead.next;
}
-
由于创建了一个新的链表,而这个新链表最后的长度为 max( len(l1), len(l2) ) + 1 ,也就是说空间复杂度为 O(max( len(l1), len(l2) ))。
-
循环的执行次数为 max( len(l1), len(l2) ) ,所以最后的时间复杂度即为 O(max( len(l1), len(l2) )) 。