1. 题目描述
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储 一位数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
来源:力扣(LeetCode)
原题传送门:link.
2. 考察知识点
链表
3. 思路
- 我们需要模拟两数相加的过程,创建第三个链表存储第一个和第二个链表的和。由于是逆序的方式,起始为个位数,无需考虑翻转链表。
- 难点是进位是的操作,我们需要清楚以下几点:
- 同位相加时,若大于等于10,那么此位只存储结果的个位并进位。
- 同位相加时,需要先考虑是否有进位,再相加。
- 还需要考虑两个链表若不等长的情况。
- 具体可看代码注释。
4. 代码(Java)
/**
* 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 dummyHead = new ListNode(0);//新建一个链表存储
ListNode p = l1, q = l2, curr = dummyHead;//三个指针指向头结点
int carry = 0;
while (p != null && q != null) {
int x = p.val;
int y =q.val;
int sum = carry + x + y;//p相加求值
carry = sum / 10;//因为carry是整型,如果sum大于10那么,carry 就会等于1
curr.next = new ListNode(sum % 10);//因为之前只创建了一个头结点,所以此处需要先创建新节点再赋值
curr = curr.next;//指针后移
p = p.next;
q = q.next;
}
if(p != null)//当两个链表不等长时进行如下操作
p.val+=(carry>0)?1:0;
curr.next = p;
if(q != null)
q.val+=(carry>0)?1:0;
curr.next = q;
return dummyHead.next;
}
}
5. 时间及空间复杂度
-
时间复杂度:O(max(m,n)),假设 m和 n分别表示 l1 和 l2 的长度,上面的算法最多重复max(m,n) 次。
-
空间复杂度:OO(max(m,n)), 新列表的长度最多为max(m,n)+1。
6. 知识积累
ListNode dummyHead = new ListNode(0);
上述命令只建了一个值为0的头结点,若扩展需要新建结点:
curr.next = new ListNode(sum % 10);