[C語言][LeetCode][2]Add Two Numbers

Problems:
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example:

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

題目是給定兩個鏈表,代表兩個非負整數。整數上的數字逆序存儲,每一個節點包括一個數字,使這兩個整數相加,然後用鏈表返回。

思路:

  1. 實際上就是一個設計一個類似加法器的東西,用鏈表的數據結構來實現。

  2. 加法器的基本思路要了解,進位帶着走。

  3. 需要考慮兩個鏈表長度不一致的情況

    1. len<min(len1,len2),公共部分的加法
    2. 當遍歷完短鏈表時,注意加法的加數減少一項
    3. 全都遍歷之後,若有進位,最高位記得新開結點去存放

C語言代碼:

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    
    struct ListNode* tmp1;
    struct ListNode* tmp2;
    struct ListNode* tmp3; //鏈表結點索引
    struct ListNode* l3 = NULL;//一開始第三個鏈表爲空,l3鏈表頭指針
    int carry=0;
    if(l1==NULL||l2==NULL)//有鏈表爲空的話直接返回
    {
        return (l1==NULL?l2:l1);
    }
    
    tmp1=l1; //索引
    tmp2=l2;
    tmp3=l3;
    while(tmp1!=NULL&&tmp2!=NULL)//處理公共部分
    {
        struct ListNode* newnode= (struct ListNode*)malloc(sizeof(struct ListNode));
        newnode->val = (tmp1->val + tmp2->val + carry)%10;
        newnode->next = NULL;
        carry = (tmp1->val + tmp2->val + carry)/10;
        
        if(l3==NULL)//如果開始鏈表爲空,那麼就填充值
        {
            l3 = tmp3 = newnode;
        }
        else//如果不空,直接將newnode接在後面
        {
            tmp3->next = newnode;
            tmp3 = tmp3->next;// tmp3始終指向鏈表末尾
        }
        tmp1 = tmp1->next;
        tmp2 = tmp2->next;
    }
    
    if(tmp1==NULL)//如果第一個鏈表遍歷完了
    {
        while(tmp2!=NULL)
        {
            struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
            newnode->val = (carry + tmp2->val)%10;
            newnode->next = NULL;
            carry = (carry + tmp2->val)/10;
            tmp3->next = newnode;
            tmp3 = tmp3->next; // tmp3移到裏l3鏈表末尾
            tmp2 = tmp2->next;
        }
        if(carry!=0) // 最高位還有進位
        {
            struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
            newnode->val = (carry)%10;
            newnode->next = NULL;
            tmp3->next = newnode;
            newnode->next = NULL;
        }
    }
    
    if(tmp2==NULL)//如果第一個鏈表遍歷完了
    {
        while(tmp1!=NULL)
        {
            struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
            newnode->val = (carry + tmp1->val)%10;
            newnode->next = NULL;
            carry = (carry + tmp1->val)/10;
            tmp3->next = newnode;

            tmp3 = tmp3->next; // tmp3移到裏l3鏈表末尾
            tmp1 = tmp1->next;
        }
        if(carry!=0) // 最高位還有進位
        {
            struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
            newnode->val = (carry)%10;
            newnode->next = NULL;
            tmp3->next = newnode;

        }
    }
    return l3;   
}

注意點

  • 如何新建結點?
  • 結構體指針變量和結構體變量對於成員的引用方式?( .->
  • 加法器設計,value = (carry + add1 + add2 )% 10; carry = (carry + add1 + add2 ) /10
  • 關於新建鏈表的問題:
  1. 新建鏈表的標準做法是新建頭結點分配結點空間,置next爲NULL,然後再用頭插法尾插法來構建鏈表。但是做題目時候注意返回的指針是頭結點後一個有值的結點
  2. 上面這種方法沒有標準頭結點,鏈表的第一個結點即有值,所以需要多加一個if判斷該結點是否爲開始結點。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章