题目描述:
个人题解:
由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加。先同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。具体而言,如果当前两个链表处相应位置的数字为 n1,n2;进位值为 carry,则它们的和为 n1+n2+carry;其中,答案链表处相应位置的数字为 (n1+n2+carry)%10,而新的进位值为(n1+n2+carry)/ 10。
如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0 。
此外,如果链表遍历结束后,有 carry>0,还需要在答案链表的后面附加一个节点,节点的值为carry。
代码实现:
struct ListNode* createListNode(int val) {
struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
node->val = val;
node->next = NULL;
return node;
}
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
// 构造哑巴节点 dummy,最后返回 dummy.next, 以方便处理新链表的头节点。
struct ListNode* dummy = createListNode(0);
struct ListNode* node = dummy; // node 一直会变化(前进)
int carrier = 0; // 进位
// 只要有没走到头的链表或者进位不为 0 就一直前进。
while (l1 != NULL || l2 != NULL || carrier != 0) {
// 求和,考虑可能有链表走到头
int sum = (l1 != NULL ? l1->val : 0) + (l2 != NULL ? l2->val : 0) + carrier;
// 在尾部添加节点
node->next = createListNode(sum % 10);
node = node->next;
// 更新进位,并向两个链表尾部前进
carrier = sum / 10;
if (l1 != NULL) l1 = l1->next;
if (l2 != NULL) l2 = l2->next;
}
return dummy->next;
}
复杂度分析:
设链表 1 的长度为 m,链表 2 的长度为 n。
时间复杂度:O(max(m,n)),其中 m 和 n 分别为两个链表的长度。需要遍历两个链表的全部位置,而处理每个位置只需要 O(1) 的时间。
空间复杂度:O(1)。注意返回值不计入空间复杂度。