给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807
解题思路:我先开始的思路是,再创建一个返回链表,然后将两个数的和放到返回链表中返回,具体处理的时候,先检查每一位相加时前面是不是有进位,如果有进位,则在相加的时候加上进位的值,在计算出每一位的和之后,如果和的值小于10,则没有进位,进位标志位false,进位值不做修改,如果有进位,则进位标志位true,进位值做相应的修改。然后我的初始代码如下:
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) { bool Carry=false; int Carry_Val=0; int temp; struct ListNode *p1,*p2,*Ret_List; p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; Ret_List=p1; p2=p1; while(l1&&l2){ if(Carry){ temp=Carry_Val+l1->val+l2->val; if(temp<10){ Carry=false; p2->val=temp; } else{ Carry=true; p2->val=temp-10;; Carry_Val=temp/10; } } else{ temp=l1->val+l2->val; if(temp<10){ Carry=false; p2->val=temp; } else{ Carry=true; p2->val=temp-10; Carry_Val=temp/10; } } l1=l1->next; l2=l2->next; if(l1||l2){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; } } while(l1){ if(Carry){ temp=Carry_Val+l1->val; if(temp<10){ Carry=false; p2->val=temp; } else{ Carry=true; p2->val=temp-10; Carry_Val=temp/10; } } else{ temp=l1->val; if(temp<10){ Carry=false; p2->val=temp; } else{ Carry=true; p2->val=temp-10; Carry_Val=temp/10; } } l1=l1->next; if(l1){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; } } while(l2){ if(Carry){ temp=Carry_Val+l2->val; if(temp<10){ Carry=false; p2->val=temp; } else{ Carry=true; p2->val=temp-10; Carry_Val=temp/10; } } else{ temp=l2->val; if(temp<10){ Carry=false; p2->val=temp; } else{ Carry=true; p2->val=temp-10; Carry_Val=temp/10; } } l2=l2->next; if(l2){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; } } if(Carry){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; p2->val=Carry_Val; } return Ret_List; }这明显太长太长了,中间有非常多的重复代码。然后我发现,我在计算Carry_Val(即进位值)的值得时候,要判断是不是有进位,但是我发现,当有进位的时候temp/10,能计算出进位的值,但是,当没有进位的时候,temp/10的值为0。这就为我提供了一个新的解题方法。代码如下:
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) { int Carry_Val=0; int temp; struct ListNode *p1,*p2,*Ret_List; p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; Ret_List=p1; p2=p1; while(l1&&l2){ temp=l1->val+l2->val+Carry_Val; p2->val=temp%10; Carry_Val=temp/10; l1=l1->next; l2=l2->next; if(l1||l2){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; } } while(l1){ temp=l1->val+Carry_Val; p2->val=temp%10; Carry_Val=temp/10; l1=l1->next; if(l1){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; } } while(l2){ temp=l2->val+Carry_Val; p2->val=temp%10; Carry_Val=temp/10; l2=l2->next; if(l2){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; } } if(Carry_Val){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p2->next=p1; p2=p1; p2->val=Carry_Val; } return Ret_List; }可以看出,代码量有了极大的简化。但是还有很多重复代码,于是我就又进行了改进,代码如下:
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) { int Carry_Val=0; int temp; struct ListNode *p1,*p2,*Ret_List; Ret_List=l1; while(l1&&l2){ temp=l1->val+l2->val+Carry_Val; l1->val=temp%10; Carry_Val=temp/10; p2=l1; l1=l1->next; l2=l2->next; } if(!l1){ p2->next=l2; l1=p2->next; } while(l1){ temp=l1->val+Carry_Val; l1->val=temp%10; Carry_Val=temp/10; p2=l1; l1=l1->next; } if(Carry_Val){ p1=(struct ListNode*)malloc(sizeof(struct ListNode)); p1->next=NULL; p1->val=Carry_Val; p2->next=p1; } return Ret_List; }
这就很nice了,空间复杂度也极大的降低了。
欢迎留言评论交流。