两数相加&c语言实现

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

你可以假设除了数字 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了,空间复杂度也极大的降低了。
欢迎留言评论交流。


你可能感兴趣的:(c)