(LeetCode) 两数相加-----C语言实现【详细讲解】

目录

1.题目要求如下: 

2.做题之前我们先来分析一下题目,看看我们究竟要做什么,怎么做?

3.下面我们将对代码进行分开讲解:

4.最后附上完整的代码供大家学习参考:


题目要求如下: 

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

示例 1:


输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.


示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]


示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
 

提示:

每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/add-two-numbers

可以看出这题就是考察的结构体,以及链表的知识。链表跟上一篇哈希表有很大的联系,哈希表里存储的数据其实就是以链表的形式储存的。

做题之前我们先来分析一下题目,看看我们究竟要做什么,怎么做?

一:给了两个非空的链表,按照逆序的方式存储。OK ,我们先不管他是“逆序”还是“顺序”,对我们来说无所谓。两数相加嘛,很简单的加法计算,因此无论是“逆序”还是“顺序”我们都按照一一对应的位置进行相加就可以了,无所谓顺序如何。

二:问题来了?仅仅是两数相加那么简单吗?如果是 9 + 2 呢?我们难道要输出这位的数字 11吗?事实证明,我们要进行——“进位”的操作,这样就满足数学的计算法则了。

三:说的那么简单,如何进行“进位”这个操作呢?别急~~   先想想,如果我们把 l1 和 l2 每一位上对应数字 n1、n2 以及进位的数字 carry,三者进行相加 ( n1 + n2 + carry ) ,得到一个“sum”(和),对吧?那么我们对这个”sum“进行 sum / 10 ,这样得到一个数字 C ,大家想想这个 C 是不是该位上对下一位的 “进位值” ?

明白了上面的操作,鼓励一下自己,本题最难的部分你已经解决了,剩下的就是对上述讲解的具体步骤的撰写。

大家跟紧了,别掉队哦!

下面我们将对代码进行分开讲解:

第一部分

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


struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode* head = NULL;  //初始化
    struct ListNode* tail = NULL;  //初始化
    int carry = 0;   //对其初始化,因为开始时并没有 进位值
    while(l1||l2)    //循环,直至 l1或者l2 的值为 0
    {
      int n1 = l1 ? l1->val :0;
      int n2 = l2 ? l2->val :0;
      int sum = n1 + n2 + carry;
      if(!head)
        {
          head = tail = malloc(sizeof(struct ListNode));
          tail->val = sum % 10;
          tail->next = NULL;
        }
      else
        {
          tail->next = malloc(sizeof(struct ListNode));
          tail->next->val = sum % 10;
          tail = tail->next;
          tail->next = NULL;
        }

 对一些着重讲解:

while(l1||l2)

{

 int n1 = l1 ? l1->val :0;

 int n2 = l2 ? l2->val :0;

//上面这两步,是运用的三目运算符 ?,其含义是int n1; if(l1!=null) n1=l1->val; else n1=0;

 int sum = n1 + n2 + carry;//求和计算,目的参考前面的问题分析

 if(!head) //如果没有头链表

   {

     head = tail = malloc(sizeof(struct ListNode));   //申请一个空间,进行动态分配

     tail->val = sum % 10;   //将 sum % 10 的值赋给 结构体 tail 的 val 值

     tail->next = NULL;  //将结构体 tail 的指针指向下一个节点

   }

 else //紧跟上面的步骤

   {

     tail->next = malloc(sizeof(struct ListNode));  //申请一个空间,进行动态分配

     tail->next->val = sum % 10;  //将 sum % 10 的值赋给 tail 的下一个节点的 val 值

     tail = tail->next;   //接着对 tail 初始化,使其转换成下一个节点(非常重要)

     tail->next = NULL;  //对 新的 tail 的下一个节点进行初始化

   }

 第二部分

      carry = sum / 10;
      if(l1)
        {
          l1 = l1->next;
        }
      if(l2)
        {
          l2 = l2->next;
        }
    }
    if(carry > 0)
      {
        tail->next = malloc(sizeof(struct ListNode));
        tail->next->val = carry;
        tail->next->next = NULL;
      }
  return head;
}

分开着重讲解 :

carry = sum / 10;  //这一步就是求该位上对下一位的 “ 进位值 ”

if(l1)

   l1 = l1->next;  //对 l1 进行 “移位”,使其移动到 l1 的下一个节点

if(l2)

   l2 = l2->next;  //对 l2 进行 “移位”,使其移动到 l2 的下一个节点

 if(carry > 0)  //进行判断,如果 carry > 0,说明,该位置对下一位有进位值,需要进位

    {

      tail->next = malloc(sizeof(struct ListNode));  //申请一个空间,进行动态分配

      tail->next->val = carry;  //将 进位值 赋给 tail 的下一个节点

      tail->next->next = NULL;  //对 tail 的下下个节点进行初始化

    }

最后附上完整的代码供大家学习参考:

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


struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode* head = NULL,* tail = NULL;
    int carry = 0;
    while(l1||l2)
    {
      int n1 = l1 ? l1->val :0;
      int n2 = l2 ? l2->val :0;
      int sum = n1 + n2 + carry;
      if(!head)
        {
          head = tail = malloc(sizeof(struct ListNode));
          tail->val = sum % 10;
          tail->next = NULL;
        }
      else
        {
          tail->next = malloc(sizeof(struct ListNode));
          tail->next->val = sum % 10;
          tail = tail->next;
          tail->next = NULL;
        }
      carry = sum / 10;
      if(l1)
        {
          l1 = l1->next;
        }
      if(l2)
        {
          l2 = l2->next;
        }
    }
    if(carry > 0)
      {
        tail->next = malloc(sizeof(struct ListNode));
        tail->next->val = carry;
        tail->next->next = NULL;
      }
  return head;
}


代码来源:力扣(LeetCode)

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简十三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值