两个数字相加

两个数字相加

题干

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

 

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

 

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

 

示例:

 

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

输出:7 -> 0 -> 8

原因:342 + 465 = 807

 

解题代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
  /*
    思路:
    1.同时遍历两个链表,直到两个链表都为空为止
    2.考虑进位的问题
    何时进位
    两个节点之和+上一位的进位>9进位
    原位变为(两个数之和+上一位的进位)%10,进位变为两个数之和+上一位的进位)/10
    考虑边界情况:
    1.只有在一个链表遍历指针不为空的情况下,才指向下一个
    2.最末位进位,所以当进位为1的时候不能结束循环
  */
    struct ListNode* t1=l1;//遍历指针,不改变原来的链表
    struct ListNode* t2=l2;
    struct ListNode* h3=(struct ListNode*)malloc(sizeof(struct ListNode));//头结点
    struct ListNode* pNew=NULL;//指向新申请的节点
    struct ListNode* pTail=h3;//指向链表的末尾
    int sum=0;
    h3->val=0;
    h3->next=NULL;//初始化头结点
    int carry=0;//向前一位的进位
    while(t1||t2||carry)
    {
        pNew=(struct ListNode*)malloc(sizeof(struct ListNode));//申请新的节点
        pNew->val=0;
        pNew->next=NULL;//申请新的节点,初始化该节点
        int sum=0;//对应项的和
        if(t1!=NULL)//只有在遍历指针不空的情况下才加上其值
        {
            sum+=t1->val;
        }
        if(t2!=NULL)
        {
            sum+=t2->val;
        }
        sum+=carry;
        if(sum>=10)
        {
            sum=sum%10;//取模
            carry=1;//进位
        }
        else
        {
            carry=0;//取消进位
        }
        pNew->val=sum;
        //将新的节点插入结果链表
        pTail->next=pNew;//插入最新链表的末尾
        pTail=pNew;//移动到尾节点
        //向下遍历链表
        if(t1!=NULL)//不空才指向下一个节点
        {
            t1=t1->next;
        }
        if(t2!=NULL)
        {
            t2=t2->next;
        }
        
    }
    struct ListNode* temp2=h3->next;
    free(h3);//释放空的头结点
    return temp2;//返回链表
}

画图分析

思路分析

整体上来说,如图所示一共有两个链表,其头结点分别是l1和l2。每一个链表的节点顺序是从头结点对应数字的低位,而尾节点对应数字的高位。我们的目的是将将两个链表按位相加,考虑进位的情况,最终得到一个新的链表,这个链表各个位对应两个链表对应数字相加的结果的各位结果。

 

如图,l1从高位到低位是1984,而l2从高位到低位是52。两个数字相加结果为2036,正好对应l3从高位到低位的2036.

 

然后我们分析一下过程,我们从低位到高位开始算,carry是进位。

* 0.初始进位为0,carray=0

* 4+2+carry=4+2+0=6 没有进位 carry=0;

* 8+5+carry=8+5+0=13 进了一位 carry=1; 值为 13%10=3

* 9+0+carry=9+0+1=10 进了一位 carry=1; 值为10%10=0

* 1+0+carry=1+0+1=2 进位为0

 

代码分析

1.为了尽可能简单,我们将创建一个新的链表来保存最终的结果,最后返回这个链表的头指针

2.在整个过程中不改变传入的两个链表

3.我们需要同时遍历两个链表

  • 何时结束?两个条件缺一不可
  • 两个链表都空的时候
  • 进位为0的时候

4.每次都要申请一个新的节点

  • 新的节点的值怎么算?如果对应两个节点的值+进位的值>9就取余数,否则就是两个节点的值+进位的值
  • 进位怎么考虑?如果对应两个节点的值+进位的值>9进位为1,否则进位为0
  •  还要考虑一个问题,如果某个链表的遍历指针指向空了怎么办?只有在遍历指针不指向空才加数值

5.插入新的链表,采用尾插法,这样才能对应顺序。

6.遍历指针后移,只有在遍历指针不为空的情况下才进行

 

posted @ 2019-08-18 21:40  梦小冷  阅读(585)  评论(0编辑  收藏  举报