动画图解“两数相加”,小学生都能看懂

网友投稿 807 2023-03-29

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

动画图解“两数相加”,小学生都能看懂

前言

大家好,我是来自于华为的程序员小熊。今天给大家带来一道各互联网大厂面试中常考的涉及到链表相关的中档题题,即力扣上的第 2 题-两数相加。

本文主要介绍迭代+虚拟头节点的策略来解答此题,供大家参考,希望对大家有所帮助。

两数相加

给你两个非空的链表,表示两个非负的整数。

它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。

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

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

示例1

其它示例及提示

解题思路

由于题目已明确告知每个节点只能存储一位数字,因此当两链表相同位置的数字之和大于 10 时,需要考虑进位的问题。

例两个链表:l1 = [3,4,3], l2 = [5,6,4]。

当他们的第二个节点的数字相加时,需要进位 1 到第三个节点的数字之和。

由于需要遍历一遍两个链表,所以考虑采用迭代的思想。

注意点

1.考虑中间位进位的问题;

例如 l1 = [3,4,3], l2 = [5,6,4]。

2.考虑最高位进位的问题。

例如 l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]。

举栗

以 l1 = [3,4,3], l2 = [5,6,4] 为例子,如下图示:

示例

不断遍历两个链表,将相同位置的节点的数值相加,并更新到新的链表;

相同位置的节点的数值相加并更新

遇到需要进位时,保留需要进位的值;

需要进位时,先保留进位

将上次进位的值与两链表本次节点的和相加;

进位更新

完整的处理过程,如下动图示:

两链表节点值相加更新到新链表,完整处理过程

Show me the Code

「C」

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){     struct ListNode *dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));     dummyHead->val = 0;     dummyHead->next = NULL;     struct ListNode *node = dummyHead;     int carry = 0;  //  进位      /* 遍历两个链表 */     for (struct ListNode* p = l1, *q = l2; p != NULL || q != NULL;) {         /* 相同位置节点值之和 */         int sum = carry;         sum += (p != NULL) ? p->val : 0;         sum += (q != NULL) ? q->val : 0;                  /* 将两链表相同位置的和的值,不断更新到新的链表 */         node->next = (struct ListNode*)malloc(sizeof(struct ListNode));         node = node->next;         node->val = sum % 10;         node->next = NULL;          /* 进位处理,两链表不断遍历 */         carry = sum / 10;         p = (p == NULL) ? p : p->next;         q = (q == NULL) ? q : q->next;     }      /* 最高位之和如果大于 10,增加一位,新链表的节点值为 1 */     if(carry != 0) {         node->next = (struct ListNode*)malloc(sizeof(struct ListNode));         node = node->next;         node->val = 1;         node->next = NULL;     }      return dummyHead->next; }

「C++」

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {     ListNode* dummyHead = new ListNode(0);       ListNode* node = dummyHead;      int carry = 0;     for (ListNode* p = l1, *q = l2; p != nullptr || q != nullptr;) {         int sum = carry;         sum += (p == nullptr) ? 0 : p->val;         sum += (q == nullptr) ? 0 : q->val;          node->next = new ListNode(sum % 10);         node = node->next;          carry = sum / 10;         p = (p == nullptr) ? p : p->next;         q = (q == nullptr) ? q : q->next;     }      if (carry != 0) {         node->next = new ListNode(carry);     }      return dummyHead->next; }

「Java」

ListNode addTwoNumbers(ListNode l1, ListNode l2) {     ListNode dummyHead = new ListNode(-1);     ListNode cur = dummyHead;      int carry = 0;     while (l1 != null || l2 != null) {         int sum = carry;         sum += (l1 == null) ? 0 : l1.val;         sum += (l2 == null) ? 0 : l2.val;          cur.next = new ListNode(sum % 10);         cur = cur.next;          carry = sum / 10;         l1 = (l1 == null) ? l1 : l1.next;         l2 = (l2 == null) ? l2 : l2.next;     }      if (carry != 0) {         cur.next = new ListNode(carry);     }      return dummyHead.next; }

「Python3」

def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:     dummyHead = ListNode(0)     node = dummyHead     carry = 0      while(l1 or l2):         sum = carry         if(l1):             sum += l1.val                             l1 = l1.next                         if l2:             sum += l2.val             l2 = l2.next          node.next = ListNode(sum % 10)         node = node.next         carry = sum//10      if carry != 0:         node.next = ListNode(carry)      return dummyHead.next

「Golang」

func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {     dummy := new(ListNode)     node := dummy     carry := 0     for l1 != nil || l2 != nil {         sum := carry         if l1 != nil {             sum += l1.Val             l1 = l1.Next         }          if l2 != nil {             sum += l2.Val             l2 = l2.Next         }          node.Next = new(ListNode)         node = node.Next         node.Val = sum % 10          carry = sum / 10     }          if carry != 0 {         node.Next = &ListNode{Val: carry}     }      return dummy.Next }

复杂度分析

时间复杂度:O(max(m, n)),其中 m 和 n 分别为两个链表的长度,需要递归调用两个链表的每个节点一次。

空间复杂度:O(1),未开辟额外存储空间。

上一篇:北塔软件以IT运维保障新疆边防安定
下一篇:花木兰新版上阵 运维创新保物流
相关文章

 发表评论

暂时没有评论,来抢沙发吧~