题目:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
输入:l1 = [0], l2 = [0]
输出:[0]
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
个人见解,算法有时候更多是数学知识,找出里面的数学规律即可解决问题的根本,剩下的就是在程序中实现我们的算法。
分析:
我们倒着取出链表中的元素不太现实,在数组中我们可以轻易的实现但是在链表中我们只能从头遍历。 通过规律我们发现,2+5=7,4+6=10,3+4=7,第二个数字是0,说明进位了,判断它是向后面仅为,也就是说3+4+1=8,这样就得到我们的7->0->8, 再对我们的示例三进行验证,也满足这个规律,不过也要考虑最后一位大于10的进位情况。
怎么操作? 可以开辟一个新的空间,也可以再长的链表上原地操作,我选择的是开辟一个新的空间。
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode* head = NULL, * tail = NULL;
int carry = 0;
while (l1 || l2) {
int n1 = l1 ? l1->val : 0;
int n2 = l2 ? l2->val : 0;
int sum = n1 + n2 + carry;
if (!head) {
head = tail = malloc(sizeof(struct ListNode));
tail->val = sum % 10;
tail->next = NULL;
}
else {
tail->next = malloc(sizeof(struct ListNode));
tail->next->val = sum % 10;
tail = tail->next;
tail->next = NULL;
}
carry = sum / 10;
if (l1) {
l1 = l1->next;
}
if (l2) {
l2 = l2->next;
}
}
if (carry > 0) {
tail->next = malloc(sizeof(struct ListNode));
tail->next->val = carry;
tail->next->next = NULL;
}
return head;
}
易错警示:经常会忘记进位操作
若选择对长的链表进行操作,需要注意最后可能要开辟一个结点接再后面,其原因是可能产生进位的1放在后面。
|