面试官:“最后再写道算法吧,就用单链表做个加法...”

开发 开发工具 算法
两数相加这道题,处理的就是最简单的数学加法运算,只是它是建立在链表的基础之上,所以难度在于对链表的处理。

[[286163]]

问:给出两个非空的链表,来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且每个结点只能存储一位数字。将这两个链表相加起来,返回一个新的链表,表示他们之和。

例如:342 + 465 = 807

 

 

两数相加这道题,处理的就是最简单的数学加法运算,只是它是建立在链表的基础之上,所以难度在于对链表的处理。

加法运算,除了每一位的加法之外,还需要考虑进位的情况。针对这道题来说,链表的每一个结点存储一位数字,并且是基于自然数字逆序存储,也就是链头到链尾保持低位到高位的顺序,这样就等于,进位的方向和单链表的方向一致。

由于单链表的特性,没有前驱结点,无法回头。在这道题的场景下,就只需要一次 while 循环,从链头(低位)一直处理到链尾(高位),就可以解决。但是需要注意处理进位的情况,每一位结点在计算之后,需要按 10 取余数,进行存储,多的需要进位到下一结点参与运算,正好这也符合单链表的处理思路。

那么我们就需要几个变量,一个 carry 用来记录每一位运算后的进位,还需要一个 dummy 结点,用于记录两个链表加法运算后的链表结点。

 

 


 

 

 

当我们处理到最长链表最后一个结点时,还需要对 carry(进位) 进行额外的处理,如果 carry 不为 0,表示继续向高位进位,需要额外在创建一个新的结点存储进位。

 

到这里就讲解清晰了,直接上代码。

  1. public ListNode addTwoNumbers(ListNode l1, ListNode l2) { 
  2.   // 计算结果存储的 dummy 结点 
  3.   ListNode dummy = new ListNode(0); 
  4.   ListNode p = l1, q = l2, curr = dummy; 
  5.   // 进位默认为 0 
  6.   int carry = 0; 
  7.   // 进入循环,以p和q两个链表指针都走到头为结束 
  8.   while (p != null || q != null) { 
  9.     int x = (p != null) ? p.val : 0; 
  10.     int y = (q != null) ? q.val : 0; 
  11.     // 进位参与运算 
  12.     int sum = carry + x + y; 
  13.     // 计算进位 
  14.     carry = sum / 10; 
  15.     // 构造新的结点存储计算后的位数数值 
  16.     curr.next = new ListNode(sum % 10); 
  17.     curr = curr.next
  18.     if (p != null)  
  19.       p = p.next
  20.     if (q != null)  
  21.       q = q.next
  22.   } 
  23.   // 处理数字最高位末尾进位情况 
  24.   if (carry > 0) { 
  25.     curr.next = new ListNode(carry); 
  26.   } 
  27.   return dummy.next

这里用 p 和 q 分别存储了 l1 和 l2 两个链表的结点,以此为循环依据。循环跳出的条件为两个链表都走到了末尾。

每一次循环中,处理每一位结点数数值并加上进位 carry 的值,运算后将数值取余存入新的结点,并将新的进位数存入 carry 进行存储。

最后需要注意,当两个链表都处理完成之后,还需要判断最高位是否需要进位(carry > 0)。如果需要,创建一个新的链表结点存储进位值。

这道利用链表做加法运算的题,就讲解到这里,但是它还有一些变种题。

假如链表不是逆序按位存储数字呢?如果是正序存储。

例如:

1 → 2 → 3

+ 3 → 2 → 1

=> 123 + 321 = ?

【本文为51CTO专栏作者“张旸”的原创稿件,转载请通过微信公众号联系作者获取授权】

 

戳这里,看该作者更多好文

 

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2022-01-10 11:04:41

单链表面试编程

2021-11-02 09:05:25

Redis

2023-02-20 08:08:48

限流算法计数器算法令牌桶算法

2021-01-06 05:36:25

拉链表数仓数据

2022-03-21 09:05:18

volatileCPUJava

2024-08-13 17:56:52

单例装饰器模式

2023-07-13 08:19:30

HaspMapRedis元素

2020-08-03 07:38:12

单例模式

2024-04-19 00:00:00

计数器算法限流算法

2024-01-15 06:42:00

高并发热点账户数据库

2022-05-23 08:43:02

BigIntJavaScript内置对象

2019-12-25 11:22:19

负载均衡集群算法

2024-09-25 12:26:14

2015-08-13 10:29:12

面试面试官

2021-12-02 18:20:25

算法垃圾回收

2022-04-10 18:10:24

CURD链表

2020-02-18 15:15:05

Handler消息队列执行任务

2022-12-06 09:03:31

MySQL索引

2021-09-30 07:57:13

排序算法面试

2023-08-02 08:48:11

C#碟片算法
点赞
收藏

51CTO技术栈公众号