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

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

[[420833]]

本文转载自微信公众号「程序员小熊」,作者Dine。转载本文请联系程序员小熊公众号。

前言

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

  1. struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){ 
  2.     struct ListNode *dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode)); 
  3.     dummyHead->val = 0; 
  4.     dummyHead->next = NULL
  5.     struct ListNode *node = dummyHead; 
  6.     int carry = 0;  //  进位 
  7.  
  8.     /* 遍历两个链表 */ 
  9.     for (struct ListNode* p = l1, *q = l2; p != NULL || q != NULL;) { 
  10.         /* 相同位置节点值之和 */ 
  11.         int sum = carry; 
  12.         sum += (p != NULL) ? p->val : 0; 
  13.         sum += (q != NULL) ? q->val : 0; 
  14.          
  15.         /* 将两链表相同位置的和的值,不断更新到新的链表 */ 
  16.         node->next = (struct ListNode*)malloc(sizeof(struct ListNode)); 
  17.         node = node->next
  18.         node->val = sum % 10; 
  19.         node->next = NULL
  20.  
  21.         /* 进位处理,两链表不断遍历 */ 
  22.         carry = sum / 10; 
  23.         p = (p == NULL) ? p : p->next
  24.         q = (q == NULL) ? q : q->next
  25.     } 
  26.  
  27.     /* 最高位之和如果大于 10,增加一位,新链表的节点值为 1 */ 
  28.     if(carry != 0) { 
  29.         node->next = (struct ListNode*)malloc(sizeof(struct ListNode)); 
  30.         node = node->next
  31.         node->val = 1; 
  32.         node->next = NULL
  33.     } 
  34.  
  35.     return dummyHead->next

「C++」

  1. ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { 
  2.     ListNode* dummyHead = new ListNode(0);   
  3.     ListNode* node = dummyHead; 
  4.  
  5.     int carry = 0; 
  6.     for (ListNode* p = l1, *q = l2; p != nullptr || q != nullptr;) { 
  7.         int sum = carry; 
  8.         sum += (p == nullptr) ? 0 : p->val; 
  9.         sum += (q == nullptr) ? 0 : q->val; 
  10.  
  11.         node->next = new ListNode(sum % 10); 
  12.         node = node->next
  13.  
  14.         carry = sum / 10; 
  15.         p = (p == nullptr) ? p : p->next
  16.         q = (q == nullptr) ? q : q->next
  17.     } 
  18.  
  19.     if (carry != 0) { 
  20.         node->next = new ListNode(carry); 
  21.     } 
  22.  
  23.     return dummyHead->next

「Java」

  1. ListNode addTwoNumbers(ListNode l1, ListNode l2) { 
  2.     ListNode dummyHead = new ListNode(-1); 
  3.     ListNode cur = dummyHead; 
  4.  
  5.     int carry = 0; 
  6.     while (l1 != null || l2 != null) { 
  7.         int sum = carry; 
  8.         sum += (l1 == null) ? 0 : l1.val; 
  9.         sum += (l2 == null) ? 0 : l2.val; 
  10.  
  11.         cur.next = new ListNode(sum % 10); 
  12.         cur = cur.next
  13.  
  14.         carry = sum / 10; 
  15.         l1 = (l1 == null) ? l1 : l1.next
  16.         l2 = (l2 == null) ? l2 : l2.next
  17.     } 
  18.  
  19.     if (carry != 0) { 
  20.         cur.next = new ListNode(carry); 
  21.     } 
  22.  
  23.     return dummyHead.next

「Python3」

  1. def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: 
  2.     dummyHead = ListNode(0) 
  3.     node = dummyHead 
  4.     carry = 0 
  5.  
  6.     while(l1 or l2): 
  7.         sum = carry 
  8.         if(l1): 
  9.             sum += l1.val                 
  10.             l1 = l1.next                 
  11.         if l2: 
  12.             sum += l2.val 
  13.             l2 = l2.next 
  14.  
  15.         node.next = ListNode(sum % 10) 
  16.         node = node.next 
  17.         carry = sum//10 
  18.  
  19.     if carry != 0: 
  20.         node.next = ListNode(carry) 
  21.  
  22.     return dummyHead.next   

「Golang」

  1. func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { 
  2.     dummy := new(ListNode) 
  3.     node := dummy 
  4.     carry := 0 
  5.     for l1 != nil || l2 != nil { 
  6.         sum := carry 
  7.         if l1 != nil { 
  8.             sum += l1.Val 
  9.             l1 = l1.Next 
  10.         } 
  11.  
  12.         if l2 != nil { 
  13.             sum += l2.Val 
  14.             l2 = l2.Next 
  15.         } 
  16.  
  17.         node.Next = new(ListNode) 
  18.         node = node.Next 
  19.         node.Val = sum % 10 
  20.  
  21.         carry = sum / 10 
  22.     } 
  23.      
  24.     if carry != 0 { 
  25.         node.Next = &ListNode{Val: carry} 
  26.     } 
  27.  
  28.     return dummy.Next 

复杂度分析

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

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

 

责任编辑:武晓燕 来源: 程序员小熊
相关推荐

2021-01-22 09:39:54

人工智能人工智能技术

2019-12-27 09:47:05

大数据TomcatWeb

2022-07-04 08:31:42

GitOpsGit基础设施

2019-10-08 10:10:52

中台 IT后台

2020-12-01 09:03:22

分库分表MySQL

2020-01-21 10:16:15

Kubernetes教程容器

2018-11-21 09:40:57

熔断实践AOP

2018-11-21 15:40:08

HTTP协议前端

2019-10-21 08:22:36

丰巢刷脸取件

2020-09-28 14:25:39

HTTPS加密算法

2020-06-22 08:07:48

Spring依赖场景

2021-09-27 13:50:13

Python装饰器函数

2019-09-05 11:14:12

监控系统拓扑图

2017-12-20 10:08:53

2023-01-26 00:22:01

分布式架构大文件

2019-01-22 09:37:47

红黑树数据二叉树

2020-08-06 13:48:16

Python 开发编程语言

2018-05-24 22:58:26

大数据分布式计算统计

2020-09-08 06:30:59

微服务代码模块

2018-11-19 08:34:22

Hadoop架构HDFS
点赞
收藏

51CTO技术栈公众号