1.两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
1 2 3 4 5 6 7 8 9 10 struct ListNode* addTwoNumbers (struct ListNode* l1, struct ListNode* l2) {}
2.个人思路 这题考察的是链表,之前写单片机程序没用过链表。。。。又是懵逼的一题,感觉c语言白学了,得恶补数据结构的知识了。
看完链表的定义后,我的想法是,创建一个变量,然后拆分链表,第三个链表值100+第二个链表值 10+头部链表,将结果保存到变量里面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 struct ListNode* addTwoNumbers (struct ListNode* l1, struct ListNode* l2) { int a[2 ] ; int num = 10 ; struct ListNode * ret = (struct ListNode*)malloc (3 *sizeof (struct ListNode)); ret -> next = NULL ; a[0 ] += l1->val ; l1->next = l1->next; a[0 ] += l1 ->val * 10 ; l1->next = l1->next; a[0 ] += l1->val * 100 ; ret->val = a[0 ]; return ret; ret = l2; a[1 ] += ret->val ; ret -> next = l2->next; a[1 ] += ret->val * 10 ; ret -> next = l2->next; a[1 ] += ret->val * 100 ; ret->val = a[0 ] + a[1 ]; return ret; }
以上是自己的,很明显遇到问题,不明白为什么l1->next = l1-> next 移动不了到下一个链表位置,l1 = l1->next也报错。一开始想使用两个for循环写的,然后数据喂想了半天处理不好,就只能一步一步来写的。又是被力扣爆扣的一题。。。。
3.正确思路 写一下加法算竖式,发现每一位相加就可以,有进位就加1。真的豁然开朗,但是指针指向下一个还未解决。
csdn之后,发现没有考虑到很多的细节。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 struct ListNode* addTwoNumbers (struct ListNode* l1, struct ListNode* l2) { struct ListNode * head = NULL ; struct ListNode * node = NULL ; int sum = 0 , cnt = 0 ; while (l1 || l2 ) { int a = l1 ? l1->val : 0 ; int b = l2 ? l2->val : 0 ; sum = a + b + cnt; if (!head) { head = node = (struct ListNode*)malloc (sizeof (struct ListNode)); node -> val = sum % 10 ; node -> next = NULL ; } else { node -> next = (struct ListNode*)malloc (sizeof (struct ListNode)); node -> next ->val = sum % 10 ; node = node ->next; node -> next = NULL ; } cnt = sum / 10 ; if (l1) l1 = l1->next; if (l2) l2 = l2->next; } if (cnt > 0 ) { node -> next = (struct ListNode*)malloc (sizeof (struct ListNode)); node -> next -> val = cnt; node -> next -> next= NULL ; } return head; }
4.官方解析 代码如上
复杂度分析
时间复杂度:O(max(m,n)),其中 m 和 n 分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要 O(1) 的时间。
空间复杂度:O(1)。注意返回值不计入空间复杂度。
看看到一个精简版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ListNode* addTwoNumbers (ListNode* l1, ListNode* l2) { ListNode* dummy = new ListNode(); ListNode* curr = dummy; int carry = 0 ; while (l1 || l2 || carry) { int a = l1 ? l1->val : 0 ; int b = l2 ? l2->val : 0 ; int sum = a + b + carry; carry = sum >= 10 ? 1 : 0 ; curr->next = new ListNode(sum % 10 ); curr = curr->next; if (l1) l1 = l1->next; if (l2) l2 = l2->next; } return dummy->next; }