【LeetCode】No.2 Add Two Numbers

版权声明:欢迎转载,但请注明出处https://me.csdn.net/qq_28753373 。谢谢! https://blog.csdn.net/qq_28753373/article/details/82499866

题目:

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.

分析:

在不考虑进位的情况下,两个多位数相加,每一位相加的结果不互相影响。此时,若两个加数是倒序的,要想得到正序的结果只需要将倒序相加的结果反向输出即可。例如,若本题给定的输入为123和456,直接相加的结果为579,由于没有进位,每一位相加的结果不相互影响,因此579就是实际的加数321和654的和975的倒序排列;本题要求把正序加数相加的结果倒序输出,因此正确的程序直接将579输出即可。

考虑进位的情况, 由对不考虑进位的情况分析可知,最理想的情况是可以把输入的数相加后的结果直接输出。在加数顺序情况下,当后一位(低位)产生进位时,前一位(高位)的数相加后的结果需再加1;在加数倒序情况下,一个数前后位的高低位关系也相应颠倒,即前一位变成了低位,后一位变成了高位,当某一位产生进位时,相应的后一位而不是前一位应加上1。

 

程序设计:

要实现分析的想法,可以直接用链表进行操作,也可将数据从链表读到数组中再进行操作。虽然数组的操作更加直观、容易理解,但显然数据的读出、数组的存储等会造成时间和空间的浪费。故我们在此直接用链表进行操作。

对两个链表进行求和操作时有两种思路,一种是将一个链表加到另一个链表中,另一种是新建一个链表来存储两个链表的和。当两个链表的长度不等时,若采取第一种思路,则应先判断哪一个链表更长,再将较短的链表加到该链表上,显然较为繁琐,故我们采用第二种思路。又因为我们需要向后一位进行进位操作,故采用尾插法(在原链表的尾部插入新的节点)建立新链表。当两个链表不一样长时,则把较长的链表多出的节点接到新链表的尾部。下面是具体的代码。

struct ListNode {
    int val;
    struct ListNode *next;
 };

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2)
{
    struct ListNode *temp1, *temp2, *rear, *sum;
    int flag = 0;    //进位标志位

    temp1 = l1;    //temp1指向第一个加数的待操作位
    temp2 = l2;    //temp2指向第二个加数的待操作位
    sum = (struct ListNode *)malloc(sizeof(struct ListNode));
    sum->next = NULL;    //sum为新链表的头结点
    rear = sum;          //rear指向新链表的最后一位

    /*对于表1和表2一样长的部分,直接相加,将和存入新的链表;若有进位,则将进位加到下一个节点*/
    while(temp1 && temp2){
        struct ListNode *cell = (struct ListNode *)malloc(sizeof(struct ListNode));
        cell->val = temp1->val + temp2->val + flag;
        if(cell->val >= 10){
            cell->val %= 10;
            flag = 1;
        }
        else{
            flag = 0;
        }
        cell->next = NULL;
        rear->next = cell;
        rear = rear->next;
        temp1 = temp1->next;
        temp2 = temp2->next;
    }

    /*表1比表2长时,将表1的剩余部分接到新链表尾部*/
    while(temp1){
        struct ListNode *extra = (struct ListNode *)malloc(sizeof(struct ListNode));
        extra->val = temp1->val + flag;  //表2的最后一个节点与表1相应节点相加时也可能产生进位
        flag = 0;
        if(extra->val >= 10){
            extra->val %= 10;
            flag = 1;
        }
        extra->next = NULL;
        rear->next = extra;
        rear = rear->next;
        temp1 = temp1->next;
    }

    /*表2比表1长,将表2的剩余部分接到新链表尾部*/
    while(temp2){
        struct ListNode *extra = (struct ListNode *)malloc(sizeof(struct ListNode));
        extra->val = temp2->val + flag;
        flag = 0;
        if(extra->val >= 10){
            extra->val %= 10;
            flag = 1;
        }
        extra->next = NULL;
        rear->next = extra;
        rear = rear->next;
        temp2 = temp2->next;
    }

    /*表1和表2一样长,但最后一个节点相加后有进位仍需要新建一个节点存储进位*/
    if(!temp1 && !temp2 && flag){
        struct ListNode *extra = (struct ListNode *)malloc(sizeof(struct ListNode));
        extra->val = flag;
        flag = 0;
        extra->next = NULL;
        rear->next = extra;
        rear = rear->next;
    }

    return sum->next;    //不返回头节点
}

这是leetcode的提交结果:

运行时间20ms,打败了100%的C提交者(自己都没想到(〃'▽'〃)!)。

下面是完整的测试代码:

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

struct ListNode {
    int val;
    struct ListNode *next;
 };

struct ListNode* CreateList();
void AddList(struct ListNode *l, int element);
struct ListNode* addTwoNumbers(struct ListNode *l1, struct ListNode *l2);
void PrintList(struct ListNode *l);

int main()
{
    struct ListNode *l1, *l2, *result;
    int size1, size2;
    int data1, data2;

    l1 = CreateList();
    l2 = CreateList();

    printf("Please input the size of the first list:\n");
    scanf("%d", &size1);
    printf("Please input the first list:\n");
    for(int i = 0; i < size1; i++){
        scanf("%d", &data1);
        AddList(l1, data1);
    }

    printf("Please input the size of the second list:\n");
    scanf("%d", &size2);
    printf("Please input the second list:\n");
    for(int i = 0; i < size2; i++){
        scanf("%d", &data2);
        AddList(l2, data2);
    }

    result = addTwoNumbers(l1->next, l2->next);
    printf("The result list is: ");
    PrintList(result);

    free(l1);
    free(l2);
    free(result);

    return 0;
}

/*新建链表*/
struct ListNode* CreateList()
{
    struct ListNode *l;

    l = (struct ListNode *)malloc(sizeof(struct ListNode));
    l->next = NULL;

    return l;
}

/*向链表中添加新的节点*/
void AddList(struct ListNode *l, int element)
{
    struct ListNode *NewNode, *temp;

    temp = l;
    NewNode = (struct ListNode *)malloc(sizeof(struct ListNode));
    NewNode->val = element;
    NewNode->next = NULL;
    while(temp->next != NULL){
        temp = temp->next;
    }
    temp->next = NewNode;
}

/*两数相加*/
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2)
{
    struct ListNode *temp1, *temp2, *rear, *sum;
    int flag = 0;

    temp1 = l1;
    temp2 = l2;
    sum = (struct ListNode *)malloc(sizeof(struct ListNode));
    sum->next = NULL;
    rear = sum;

    while(temp1 && temp2){
        struct ListNode *cell = (struct ListNode *)malloc(sizeof(struct ListNode));
        cell->val = temp1->val + temp2->val + flag;
        if(cell->val >= 10){
            cell->val %= 10;
            flag = 1;
        }
        else{
            flag = 0;
        }
        cell->next = NULL;
        rear->next = cell;
        rear = rear->next;
        temp1 = temp1->next;
        temp2 = temp2->next;
    }

    /*表1比表2长*/
    while(temp1){
        struct ListNode *extra = (struct ListNode *)malloc(sizeof(struct ListNode));
        extra->val = temp1->val + flag;
        flag = 0;
        if(extra->val >= 10){
            extra->val %= 10;
            flag = 1;
        }
        extra->next = NULL;
        rear->next = extra;
        rear = rear->next;
        temp1 = temp1->next;
    }

    /*表2比表1长*/
    while(temp2){
        struct ListNode *extra = (struct ListNode *)malloc(sizeof(struct ListNode));
        extra->val = temp2->val + flag;
        flag = 0;
        if(extra->val >= 10){
            extra->val %= 10;
            flag = 1;
        }
        extra->next = NULL;
        rear->next = extra;
        rear = rear->next;
        temp2 = temp2->next;
    }

    /*表1和表2一样长,且相加后最高位有进位*/
    if(!temp1 && !temp2 && flag){
        struct ListNode *extra = (struct ListNode *)malloc(sizeof(struct ListNode));
        extra->val = flag;
        flag = 0;
        extra->next = NULL;
        rear->next = extra;
        rear = rear->next;
    }

    return sum->next;
}

/*顺序打印链表*/
void PrintList(struct ListNode *l)
{
    struct ListNode *p;

    p = l;
    while(p != NULL){
        printf("%d", p->val);
        p = p->next;
    }
    printf("\n");
}

猜你喜欢

转载自blog.csdn.net/qq_28753373/article/details/82499866