1. 程式人生 > >LeetCode | Add Two Numbers(兩個連結串列相加)

LeetCode | Add Two Numbers(兩個連結串列相加)

題目:

You are given two linked lists representing two non-negative numbers. 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.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8


題意解析:

題目就是將兩個連結串列對應位的數目進行相加,但如果超過十的話,需要進1,跟整數的加法一樣,只是每個結點儲存1位。

題目很簡單,並且看到樣例更會受到誤導。需要先考察連結串列L1和連結串列L2的長度,哪一個比較長。當最後一位相加後再產生進位,也要單獨處理。還有,我們建立連結串列的時候是在表頭插入還是在表尾插入等等。這些方面都要考慮。

方案一:

這個是我的方法,將L2的資料加到L1上,當L2的長度比L1長的話,將多出的結點連結到L1上。(這裡就導致一個問題,當我們最後銷燬兩個連結串列的時候,L2和L1有了公共結點,會導致系統崩潰。需要額外處理,不過我沒有加上這段程式碼,只是設定q的父節點,當L2後續結點連結到L1後,將q的父節點的next指標設為空即可。)最末尾的時候,要單獨處理一下進位。

#include <stdio.h>
#include <stdlib.h>

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;

LinkList InitList(void)
{
    LinkList head = (LinkList)malloc(sizeof(LNode));
    if(head == NULL){
        printf("Memory allocation failure!\n");
        exit(1);
    }
    head->next = NULL;

    return head;
}

void CreateList(LinkList head,int data)
{
    LinkList p = (LinkList)malloc(sizeof(LNode));
    if(!p){
        printf("Memory allocation failure!\n");
        exit(1);
    }
    p->data = data;
    p->next = head->next;
    head->next = p;
}


void AddList(LinkList dest,LinkList src)
{
    LinkList p,q,parent;
    int carryover = 0;

    if(!dest || !src){
        printf("NULL!");
        exit(1);
    }
    parent = dest;
    p = parent->next;
    q = src->next;
    while(p && q){
        p->data += q->data + carryover;
        carryover = p->data / 10;
        p->data %= 10;
        parent = p;
        p = parent->next;
        q = q->next;
    }
    if(q)   // q->length > p->length
        parent->next = q;
    q = parent->next;   //將q->length > p->length統一到q->length < p->length上

    while(carryover && q){  //如果進位存在,並且q不為空指標的時候,將carryover加到q->data上
        q->data += carryover;
        carryover = q->data / 10;
        q->data %= 10;
        parent = q;
        q = q->next;
    }
    if(carryover){  //單獨處理進位
        LinkList Q = (LinkList)malloc(sizeof(LNode));
        if(!Q)
            exit(1);
        Q->data = carryover;
        Q->next = NULL;
        parent->next = Q;
    }
}

void PrintList(LinkList head)
{
    LinkList p = head->next;
    while(p){
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
}

void DestoryList(LinkList head)
{
    LinkList p = head->next,q;
    head->next = NULL;
    while(p){
        q = p->next;
        free(p);
        p = q;
    }
}



int main(void)
{
    int n,m,data;
    LinkList dest,src;

    dest = InitList();
    src = InitList();
    printf("input how many numbers of n and m:");
    while(scanf("%d %d",&n,&m) == 2){
        printf("input the n+m datas:");
        for(int i = 0;i < n;++i){
            scanf("%d",&data);
            CreateList(dest,data);
        }
        for(int i = 0;i < m;++i){
            scanf("%d",&data);
            CreateList(src,data);
        }

        AddList(dest,src);
        PrintList(dest);

        printf("input how many numbers of n and m:");
    }

    return 0;
}


方案二:

如果這個題目,建立第三方連結串列會更方便,並且將L1->data 、L2->data和carryover三個數相加,分兩次進行,會簡化思路,得到更好的效果。下面這段程式碼摘自網路,很值得學習!

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
		ListNode* ret = NULL;
		ListNode** cur = &ret;
		int carry = 0;
		int sum = 0;

		while(l1 != NULL || l2 != NULL)
		{
			sum = carry;
			if(l1 != NULL)
			{
				sum += l1->val;
				l1 = l1->next;
			}
			if(l2 != NULL)
			{
				sum += l2->val;
				l2 = l2->next;
			}

			carry = sum/10;
			sum %= 10;
			*cur = new ListNode(sum);
			cur = &(*cur)->next;
		}

        if(carry > 0)
			*cur = new ListNode(carry);

		return ret;
    }
};