题目描述:给定两个非空的链表,链表存储非负整数,但是数据在链表中是倒叙存储,将两个链表中的数据相加到一个链表中
example:
- 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
- 输出:7 -> 0 -> 8
- 检查:342 + 465 = 807
我的代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
auto it1=l1;
auto it2=l2;
int length1=1;
int length2=1;
while(it1->next!=NULL)
{
it1=it1->next;
length1++;
}
while(it2->next!=NULL)
{
it2=it2->next;
length2++;
}
if(it1->next==NULL)
{
if(it1->val==0)
return l2;
}
if(it2->next==NULL)
{
if(it2->val==0)
return l1;
}
it1=l1,it2=l2;
if(length1>=length2)
{
for(int i=1;i<=length2;i++)
{
it1->val=it1->val+it2->val;
it1=it1->next;
it2=it2->next;
}
it1=l1;
int cf=0;
for(int i=1;i<=length1;i++)
{
if(it1->val>=9&&it1->next!=NULL)
{
if(it1->val>=10)
{
it1->val=it1->val-10+cf;
cf=1;
}
else
{
if(cf==1)
it1->val=it1->val-10+cf;
}
}
else if(it1->val<9&&it1->next!=NULL)
{
it1->val+=cf;
cf=0;
}
else if(it1->next==NULL)
{
if(it1->val==9)
{
if(cf==1)
{
it1->val+=cf;
it1->val-=10;
ListNode* l3=new ListNode(1);
if(l3!=NULL)
it1->next=l3;
}
}
else if(it1->val>=10)
{
it1->val+=cf;
it1->val-=10;
ListNode* l3=new ListNode(1);
if(l3!=NULL)
it1->next=l3;
}
else
it1->val+=cf;
}
it1=it1->next;
}
return l1;
}
if(length1<length2)
{
for(int i=1;i<=length1;i++)
{
it2->val=it1->val+it2->val;
it1=it1->next;
it2=it2->next;
}
it2=l2;
int cf=0;
for(int i=1;i<=length2;i++)
{
if(it2->val>=9&&it2->next!=NULL)
{
if(it2->val>=10)
{
it2->val=it2->val-10+cf;
cf=1;
}
else
{
if(cf==1)
it2->val=it2->val-10+cf;
}
}
else if(it2->val<9&&it2->next!=NULL)
{
it2->val+=cf;
cf=0;
}
else if(it2->next==NULL)
{
if(it2->val==9)
{
if(cf==1)
{
it2->val+=cf;
it2->val-=10;
ListNode* l3=new ListNode(1);
if(l3!=NULL)
it2->next=l3;
}
}
else if(it2->val>=10)
{
it2->val+=cf;
it2->val-=10;
ListNode* l3=new ListNode(1);
if(l3!=NULL)
it2->next=l3;
}
else
it2->val+=cf;
}
it2=it2->next;
}
return l2;
}
return NULL;
}
};
运行情况:
- runtime:24ms
- memory usage:9.8MB
代码缺陷:由于我思考问题时考虑的少了,所以写代码时是想一点写一点,写的很痛苦,但磕磕绊绊写完了并且运行了,但这样写代码效率极低,并且错误很多,下次一定注意。
然后看看官方的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 != 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;
}
看完后很崩溃,很简单的代码让我写了那么多,写之前还是要思考全面。
分析:该题目没有必要将节点中的数取出来相加再放回去,从两个链表的第一个节点开始加,如果第一组相加超过10,那么进位标志置carry=1,并且下一组相加后的和sum要+carry,一次类推,外部循环while控制长度,只有在两个链表都到头时才退出。
另外,最后一个节点如果超过10,需要创建一个新的节点来接受,要用到new。
复杂度分析:因为循环的次数也就是两个链表中长度较长的那个,所以O(n)=max(l1.size(),l2.size());
总结:一定要想好了再写,先写出伪代码有助于思考。