002.Java实现两数相加

news2024/9/22 19:35:18

题意

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

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

示例

输入:l1=[2,4,3],l2=[5,6,4]

输出:[7,0,8]

解释:342+465=807

  1. l1 存储的是 2、4、3,也就是整数 342,逆序嘛;
  2. l2 存储的是 5、6、4,也就是整数 465,逆序嘛;
  3. 个位相加为 7(2+5),十位相加为 10(4+6,需要进位),百位相加为 7(3+4),加上进位的 1 就是 8

难度

中等

分析

首先,搞清楚“逆序”是什么。

逆序:从后往前的顺序,比如 123 的逆序是 321。

题目中的示例其实也给出了解释,假如逆序链表 l1 为 [2,4,3],l2 为 [5,6,4],那么 l1 代表的数字就是 342,l2 为 456。

对于还没有学过链表的球友来说,可以通过二哥的 Java 进阶之路中的LinkedList来学习一下链表的数据结构,大体上就这样:a->b->c->d

两数相加,如果不需要进位的话,就是把对应位置的数字相加,比如 342 + 456 = 798,非常简单。

难点就在于,进位该如何处理。

回想一下我们小学曾经学过的加法竖式,如下图。

对于每一位上的数字相加,都有可能产生进位,比如 4 + 6 = 10,那么 1 就是进位,我们需要把它加到下一位的和中即可。

假设两个链表相同位置的数字分别是 addX 和 addY,进位是 up,那么它们的和(sum)就是 addX + addY + up,如果 sum 大于 10 的话,需要进位,那么进位的值就是 sum / 10,而 sum % 10 就是当前位置的数字。

比如说个位 7+8=15(此时进位为 0),由于和大于 10,所以十位的进位就是 1(sum / 10),个位的数字就是 5(sum % 10)。

十位 4+6+1=11(此时进位为 1),由于和大于 10,所以百位的进位就是 1(sum / 10), 十位的数字就是 1(sum % 10)。

百位 3+5+1=9(此时进位为 1),由于和小于 10,所以千位的进位就是 0(sum / 10),百位的数字就是 9(sum % 10)。

也就是说 347(对应的逆序链表为「7、4、3」)+568(对应的逆序链表为「8、6、5」)=915(新的逆序链表为 5、1、9),这就是我们最终的结果。

  1. 7+8=15,进位为 1,个位为 5;
  2. 4+6+1=11,进位为 1,十位为 1;
  3. 3+5+1=9,进位为 0,百位为 9。

是不是突然发现,逆序链表的顺序和我们的计算顺序恰好是一样的,这样子就方便我们直接进行处理。

假如不是逆序的,那么我们就需要先把链表反转,然后再进行计算,最后再把结果反转回来。

妙啊!

/**

*Definitionforsingly-linkedlist.

*public  class  ListNode{

*int  val;

*ListNode  next;

*ListNode(){}

*ListNode(intval){this.val=val;}

*ListNode(int  val,ListNode  next){this.val=val;this.next=next;}

*}

*/

class  Solution{

public  ListNodeaddTwoNumbers( ListNode l1, ListNode l2){

ListNode  dummyHead = new  ListNode(0);//创建一个哨兵节点,方便返回结果

ListNode p = l1,q = l2,curr = dummyHead;//初始化三个指针:p和q分别遍历两个输入链表,curr用于构建结果链表

int carry = 0;//初始化进位值为0



//遍历两个链表直到全部结束

while(p! = null || q! = null){

//获取当前节点的值,如果节点不存在则为0

int x = (p!=null)?p.val:0;

int y = (q!=null)?q.val:0;

//计算两个值和进位值的总和

int  sum = carry + x + y;

//更新进位值

carry = sum/10;

//创建新节点,值为总和的个位数,并将其加入到结果链表

curr.next = newListNode(sum%10);

//移动curr指针到新节点

curr = curr.next;

//如果存在,移动p和q到各自链表的下一个节点

if(p!=null)  p=p.next;

if(q!=null)  q=q.next;

}

//循环结束后,如果仍有进位,则在结果链表末尾添加一个节点

if(carry>0){

curr.next=newListNode(carry);

}

//返回哨兵节点的下一个节点,即结果链表的头节点

return  dummyHead.next;

}

}

当输入是 l1 = [2,4,3] 和 l2 = [5,6,4] 时,我们来模拟一下整个题解过程:

  1. 初始化:创建一个哨兵节点 dummyHead 用于简化边界情况的处理,以及一个临时节点 curr 指向它。设置进位 carry 为 0。
  2. 开始遍历两个链表
  3. 第一轮迭代
  4. l1 的当前元素是 2,l2 的当前元素是 5。
  5. 计算和:sum = 2 + 5 + 0 = 7(当前进位 carry 是 0)。
  6. 创建新节点,值为 sum % 10 = 7,进位 carry = sum / 10 = 0。
  7. 移动 curr 到新节点。
  8. 移动 l1 和 l2 分别到下一个节点。
  9. 第二轮迭代
  10. l1 的当前元素是 4,l2 的当前元素是 6。
  11. 计算和:sum = 4 + 6 + 0 = 10(当前进位 carry 是 0)。
  12. 创建新节点,值为 sum % 10 = 0,进位 carry = sum / 10 = 1。
  13. 移动 curr 到新节点。
  14. 移动 l1 和 l2 分别到下一个节点。
  15. 第三轮迭代
  16. l1 的当前元素是 3,l2 的当前元素是 4。
  17. 计算和:sum = 3 + 4 + 1 = 8(当前进位 carry 是 1)。
  18. 创建新节点,值为 sum % 10 = 8,进位 carry = sum / 10 = 0。
  19. 移动 curr 到新节点。
  20. l1 和 l2 都没有下一个节点,结束遍历。
  21. 检查最后的进位
  22. 检查 carry 是否大于 0。此处 carry = 0,所以不需要添加新节点。
  23. 返回结果
  24. 返回 dummyHead.next,即哨兵节点后的链表。结果为 7 -> 0 -> 8。

342+465=807,我们得到了正确的答案。

时间复杂度:

空间复杂度:

我擦嘞,竟然打败了 100% 的用户!

总结

本题其实是一个铺垫,就比如说给你了一个非常非常大的数,用 int、long 根本无法装下,那其实就可以把这个数简化为一个链表,每个节点存储一个数位,这样子就可以无限扩展了。

其实这道题的内核就是大数相加,只不过我们把大数用链表来表示了,并且题目限制了每个链表中的节点数在范围 [1, 100] 内。

其实计算机中的大多数思想都是这样的,当一个问题超复杂时,我们就简化它,把它拆分成一个个小问题,然后再去解决。

关于 while 循环和链表的知识,我这里补充一下学习资料。

  1. while 循环
  2. 链表(Linked list)
  3. LinkedList 和 ArrayList 的区别

力扣链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

一步一个脚印

不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1316102.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT4 Excel 高级复杂函数案例实践

案例需求: 需求中需要判断多个条件进行操作。 可以让ChatGPT来实现这样的操作。 Prompt:有一个表格B2单元格为入职日期,C2单元格为员工等级(A,B,C),D2单元格为满意度分数(1,2,3,4,5)请给入职一年以上,员工等级为A级并且满意度在3分以上的人发4000元奖金,给入…

普冉(PUYA)单片机开发笔记(10): I2C通信-配置从机

概述 I2C 常用在某些型号的传感器和 MCU 的连接,速率要求不高,距离很短,使用简便。 I2C的通信基础知识请参见《基础通信协议之 IIC详细讲解 - 知乎》。 PY32F003 可以复用出一个 I2C 接口(PA3:SCL,PA2&a…

计算机组成原理-函数调用的汇编表示(call和ret指令 访问栈帧 切换栈帧 传递参数和返回值)

文章目录 call指令和ret指令高级语言的函数调用x86汇编语言的函数调用call ret指令小结其他问题 如何访问栈帧函数调用栈在内存中的位置标记栈帧范围:EBP ESP寄存器访问栈帧数据:push pop指令访问栈帧数据:mov指令小结 如何切换栈帧函数返回时…

深度学习记录--矩阵维数

如何识别矩阵的维数 如下图 矩阵的行列数容易在前向和后向传播过程中弄错,故写这篇文章来提醒易错点 顺便起到日后查表改错的作用 本文仅作本人查询参考(摘自吴恩达深度学习笔记)

Flink系列之:SQL提示

Flink系列之:SQL提示 一、动态表选项二、语法三、例子四、查询提示五、句法六、加入提示七、播送八、随机散列九、随机合并十、嵌套循环十一、LOOKUP十二、进一步说明十三、故障排除十四、连接提示中的冲突案例十五、什么是查询块 SQL 提示可以与 SQL 语句一起使用来…

MyBatis Plus 大数据量查询优化

大数据量操作的场景大致如下: 数据迁移 数据导出 批量处理数据 在实际工作中当指定查询数据过大时,我们一般使用分页查询的方式一页一页的将数据放到内存处理。但有些情况不需要分页的方式查询数据或分很大一页查询数据时,如果一下子将数…

【单元测试】Junit 4--junit4 内置Rule

1.0 Rules ​ Rules允许非常灵活地添加或重新定义一个测试类中每个测试方法的行为。测试人员可以重复使用或扩展下面提供的Rules之一,或编写自己的Rules。 1.1 TestName ​ TestName Rule使当前的测试名称在测试方法中可用。用于在测试执行过程中获取测试方法名称…

MATLAB 计算两片点云间的最小距离(2种方法) (39)

MATLAB 计算两片点云间的最小距离 (39) 一、算法介绍二、算法实现1.常规计算方法2.基于KD树的快速计算一、算法介绍 假设我们现在有两片点云 1 和 2 ,需要计算二者之间的最小距离,这里提供两种计算方法,分别是常规计算和基于KD树近邻搜索的快速计算方法,使用的测试数据如…

Java 分布式框架 —— Dubbo 快速入门

1 分布式系统中的相关概念 1.1 大型互联网项目架构目标 传统项目和互联网项目 传统项目:例如 OA、HR、CRM 等,服务对象为:企业员工 互联网项目:天猫、微信、百度等,服务对象为:全体网民 互联网项目特点…

2 使用postman进行接口测试

上一篇:1 接口测试介绍-CSDN博客 拿到开发提供的接口文档后,结合需求文档开始做接口测试用例设计,下面用最常见也最简单的注册功能介绍整个流程。 说明:以演示接口测试流程为主,不对演示功能做详细的测试,…

JVM学习之JVM概述

JVM的整体结构 Hotspot VM是目前市面上高性能虚拟机代表作之一 它采用解释器与即时编译器并存的架构 在今天,Java程序的运行性能已经达到了可以和C/C程序一较高下的地步 Java代码执行流程 具体图为 JVM架构模型 Java编译器输入的指令流基本上是一种基于 栈的指令…

drf入门规范

一 Web应用模式 在开发Web应用中,有两种应用模式: 1.1 前后端不分离 1.2 前后端分离 二 API接口 为了在团队内部形成共识、防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写…

【MySQL内置函数】

目录: 前言一、日期函数获取日期获取时间获取时间戳在日期上增加时间在日期上减去时间计算两个日期相差多少天当前时间案例:留言板 二、字符串函数查看字符串字符集字符串连接查找字符串大小写转换子串提取字符串长度字符串替换字符串比较消除左右空格案…

79.55 Gbps!已经初步测得VMWare ESXi 6.7的vSwitch转发性能

正文共:1234 字 14 图,预估阅读时间:1 分钟 在前面的文章中,我们提到了测试主要分为3个内容: 一是测试iperf和iperf3两个工具的实用性,目前的结论是iperf可以支持多CPU、多线程,整体测试结果比i…

Linux——进程创建与进程终止

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、进程创建1、fork函数初识2、fork函数返回值3、写时拷贝4、fork常规用法5、fork调用失败的…

Java从properties文件读取内容

例如,项目文件布局: test.properties文件的内容为: name thb pass 223355主类文件: package com.thb;import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java…

Java数据结构篇——单链表的基本操作

1. 前言 在上一篇《Java数据结构篇——实现顺序表的增删查改》,我们已经熟悉了 ArrayList 的使用并且进行了简单的模拟实现。ArrayList底层使用数组来存储元素,由于其底层是一段连续的空间,当ArrayList 任意位置插入或者删除元素时&#xff…

紫光展锐T820与飞桨完成I级兼容性测试 助推端侧AI融合创新

近日,紫光展锐高性能5G SoC T820与百度飞桨完成I级兼容性测试(基于Paddle Lite工具)。测试结果显示,双方兼容性表现良好,整体运行稳定。这是紫光展锐加入百度“硬件生态共创计划”后的阶段性成果。 本次I级兼容性测试完…

2023年最详细的:本地Linux服务器安装宝塔面板,并内网穿透实现公网远程登录

📚📚 🏅我是默,一个在CSDN分享笔记的博主。📚📚 ​​ 🌟在这里,我要推荐给大家我的专栏《Linux》。🎯🎯 🚀无论你是编程小白,还是有一…

linux环境安装可操作图库语言Gremlin的图框架HugeGraph

原创/朱季谦 若你还没接触过图数据库,可能看到这个概念时,会比较蒙蔽。 图是什么?图数据库又是什么? 首先,在数据结构中,图是一种由顶点(vertex)集合及顶点间关系集合组成的一种非…