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;
    }
};

点赞