目录
1.题目要求如下:
2.做题之前我们先来分析一下题目,看看我们究竟要做什么,怎么做?
题目要求如下:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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)