图解算法:单向链表做加法运算

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

例如:342 + 465 = 807

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

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

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

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

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

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

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
  // 计算结果存储的 dummy 结点
  ListNode dummy = new ListNode(0);
  ListNode p = l1, q = l2, curr = dummy;
  // 进位默认为 0
  int carry = 0;
  // 进入循环,以p和q两个链表指针都走到头为结束
  while (p != null || q != null) {
    int x = (p != null) ? p.val : 0;
    int y = (q != null) ? q.val : 0;
    // 进位参与运算
    int sum = carry + x + y;
    // 计算进位
    carry = sum / 10;
    // 构造新的结点存储计算后的位数数值
    curr.next = new ListNode(sum % 10);
    curr = curr.next;
    if (p != null)
      p = p.next;
    if (q != null)
      q = q.next;
  }
  // 处理数字最高位末尾进位情况
  if (carry > 0) {
    curr.next = new ListNode(carry);
  }
  return dummy.next;
}

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

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

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

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

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

例如:

1 → 2 → 3

+3 → 2 → 1

=> 123 + 321 = ?

那么如何计算呢?

本文对你有帮助吗?留言、转发、收藏是最大的支持,谢谢!


公众号后台回复成长『成长』,将会得到我准备的学习资料。

原文地址:https://www.cnblogs.com/plokmju/p/linked_add.html

时间: 2024-08-11 03:29:42

图解算法:单向链表做加法运算的相关文章

编程算法 - 不用加减乘除做加法 代码(C)

不用加减乘除做加法 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 写一个函数, 求两个整数之和, 要求在函数体内不得使用+, -, *, /四则运算符号. 不能使用运算符号, 使用位运算, 第一步异或运算选位, 第二步与运算进位. 代码: /* * main.cpp * * Created on: 2014.7.13 * Author: Spike */ #include <iostream> #include <list>

算法学习(6)----不用 + - &#215; &#247; 做加法运算

今天网上看到一个神算法,惊异不已,遂摘录于下: 原文地址:http://blog.csdn.net/sanniao/article/details/47106713 第一步不考虑进位,对每一位相加.0加0与 1加1的结果都0,0加1与1加0的结果都是1.我们可以注意到,这和异或的结果是一样的.对异或而言,0和0.1和1异或的结果是0,而0和1.1和0的异或结果是1.接着考虑第二步进位,对0加0.0加1.1加0而言,都不会产生进位,只有1加1时,会向前产生一个进位.此时我们可以想象成是两个数先做位

数据结构与算法-单向链表

概述 由于最近在工作中需要用到树形结构来解决一些问题,所以萌生了系统学习“数据结构和算法”的想法,于是乎从最简单的表结构开始.由于数组是最简单的表结构的实现,也是各个编程语言内置的数据类型,所以不做更多的记录.表结构中以下实现打算学习: LinkedList Stack Queue HashTable Dictionary 本篇为学习数据结构的第一篇随笔,从最简单的单向链表开始吧. 实现(C#) 平台:dotNet Core 1.0, C# IDE:VSCode 如果考虑算法复用的话,可以实现泛

PTA 6-14 用单向链表完成多项式运算 (35 分)

输入两个多项式,计算它们的加.减及乘法, 将计算结果输出到屏幕上. 1) 输入:从键盘分两行分别输入两个多项式数据,每个多项式输入格式如下: n a1 m1 a2 m2 a3 m3 . .. ai mi.... an mn 其中n为多项式系数为非零的项数,ai为系数,mi为指数, 它们都是整数,该输入数据所表达的多项式意义为(其中符号^表示幂次): a1x^m1 + a2x^m2 + a3x^m3 + ...... + an x^mn 2)输出:先输出参与运算的两个多项式, 然后输出它们的运算结

数据结构与算法 —— 单向链表的逆转

1 List Reverse(List L) 2 { 3 Node *new_head, *old_head, temp; 4 new_head = NULL; 5 old_head = L; 6 while(old_head) 7 { 8 temp = old_head->next; 9 old_head->next = new_head; 10 new_head = old_head; 11 old_head = temp; 12 } 13 14 L = new_head; 15 retu

通过按钮做加法运算

1 package su; 2 3 import java.awt.GridLayout; 4 import java.awt.event.ActionEvent; 5 import java.awt.event.ActionListener; 6 7 import javax.swing.JButton; 8 import javax.swing.JFrame; 9 import javax.swing.JLabel; 10 import javax.swing.JPanel; 11 impo

(笔试题)只用逻辑运算实现加法运算

题目: 如题所示 思路: 逻辑运算,即二进制运算,无外乎与&.或|.非~.异或^以及移位>>,<<等操作: 而加法运算,在十进制中,只有按位相加以及进位两个操作. 从二进制角度也一样,就是bit位相加,加上相应的进位. 1.bit位相加,通过逻辑运算的异或操作可以实现,如0+1=1,1+0=1,0+0=0: 2.进位运算,通过逻辑运算的与操作可以实现,如1+1=1,因为进位是往高位+1,因此需要将进位结果左移一位. 将上述两个操作再做加法运算,就是加法运算的结果,这是一个递

【 c语言中无符号和有符号的加法运算】【深入理解】--【sky原创】

原文:[ c语言中无符号和有符号的加法运算][深入理解]--[sky原创] 第一题 #include<stdio.h> int main() { unsigned int a=6; int b=-20; printf("%d\n",a+b); (a+b)>6? puts(">6"):puts("<=6"); return 0; } 答案是:>6 第二题 #include<stdio.h> int m

【Simple Java】面试问题-使用Java线程做数学运算

这是一个展示如何使用join()方法的例子. 问题: 使用Java多线程计算表达式1*2/(1+2)的值. 解决方案: 使用一个线程做加法运算,另一个线程做乘法运算,还有一个主线程main做除法运算.由于线程之间不需要通讯,所以我们只需要考虑线程的执行顺序. 在main线程中,我们让加法运算线程和乘法运算线程join到主线程,join()方法的作用是使main方法等待,直到调用join的线程执行完毕.在这个例子中,我们希望加法运算线程和乘法运算线程先结束,然后在计算除法运算. package s