题目描述:
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
分析:
因为数据是按逆序存储,所以存储顺序和我们实际算术计算的顺序是一致的。
每次计算的结果是进位的数据和对应位置相加的和再模10,将该结果赋给当前变量,并且每次需要更新进位的数据;然后将指针后移,判断后移之后是否为空,如果全部为空并且进位数据为0则不需要再申请结点;如果全部为空但是进位数据大于0,需要申请节点,循环结束之后需要重新为申请的节点赋值。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode r=new ListNode(0);
ListNode p=l1,q=l2,temp=r;
int add=0;
while(p!=null||q!=null){
int x=0,y=0;
if(p!=null)
x=p.val;
if(q!=null)
y=q.val;
int sum=x+y+add;
add=sum/10;
temp.val=sum%10;
if(p!=null)
p=p.next;
if(q!=null)
q=q.next;
if(p!=null||q!=null||add>0){
temp.next=new ListNode(0);
temp=temp.next;
}
}
if(p==null&&q==null&&add>0)
temp.val=add;
return r;
}
}
这种方法是利用哑结点实现,即第一个节点不存在数据最终返回的是哑结点所指向的结点。
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dummyHead;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummyHead.next;
}
复杂度分析:
时间复杂度:O(max(m, n))。假设 m 和 n 分别表示 l1 和 l2的长度,上面的算法最多重复 max(m,n) 次。
空间复杂度:O(max(m, n)), 方法一新列表的长度最多为 max(m,n),
方法二的长度最多为max(m,n)+1。