002.Java实现两数相加

题意

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

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

示例

输入: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天从算法小白到卷王正式启动了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【从零开始学习JVM | 第七篇】深入了解 堆回收

前言: Java堆作为内存管理中最核心的一部分,承担着对象实例的存储和管理任务。堆内存的高效使用对于保障程序的性能和稳定性至关重要。因此,深入理解Java堆回收的原理、机制和优化策略,对于Java开发人员具有重要的意义。 本文旨在…

springcloud-分布式缓存

文章目录 一.Redis持久化1.RDB持久化2.AOF持久化 二.Redis主从1.搭建主从架构2.全量同步3.增量同步 三.Redis哨兵1.哨兵的作用和原理2.搭建哨兵架构3.RedisTemplate的哨兵模式 四.Redis分片集群1.搭建分片集群2.散列插槽3.集群伸缩4.故障转移5.RedisTemplate访问分片集群 为什么…

树莓派(Raspberry Pi)4B密码忘记了,怎么办?

树莓派长时间不用,导致密码忘记了,这可咋整? 第1步:取出SD卡 将树莓派关机,移除sd卡,使用读卡器,插入到你的电脑。 第2步:编辑 cmdline.txt 在PC上打开SD卡根目录,启动…

Kotlin ArrayList类型toTypedArray转换Array

Kotlin ArrayList类型toTypedArray转换Array data class Point(val x: Float, val y: Float)fun array_test(points: ArrayList<Array<Point>>) {points.forEachIndexed { idx, ap ->ap.forEach {print("$idx $it ")}println()} }fun main(args: Arra…

2697. 字典序最小回文串

2697. 字典序最小回文串 难度: 简单 来源: 每日一题 2023.12.13 给你一个由 小写英文字母 组成的字符串 s &#xff0c;你可以对其执行一些操作。在一步操作中&#xff0c;你可以用其他小写英文字母 替换 s 中的一个字符。 请你执行 尽可能少的操作 &#xff0c;使 s 变…

RTX 40 SUPER发布时间定了!价格也有了

快科技12月16日消息&#xff0c;NVIDIA RTX 40 SUPER系列显卡基本确定将在2024年1月8日正式发布&#xff0c;也就是CES 2024大展期间&#xff0c;随后在1月中下旬陆续解禁上市。 RTX 4070 SUPER 1月16日解禁公版/原价丐版&#xff0c;1月17日解禁高价高配版&#xff0c;上市开…

鸿蒙开发编辑器设置

首先需要知道如何打开设置页面&#xff0c;以下所有设置都需要在设置界面中进行修改&#xff0c;有三种方式可以打开&#xff0c; 1、编辑器左上角file菜单下的Setting菜单。 2、编辑器右上角的设置按钮 3、按快捷键 ctrlalts 注意不要和其他软件案件重复。 一、设置每次打开…

制作一个简单 的maven plugin

流程 首先&#xff0c; 你需要创建一个Maven项目&#xff0c;推荐用idea 创建项目 会自动配置插件 pom.xml文件中添加以下配置&#xff1a; <project> <!-- 项目的基本信息 --> <groupId>com.example</groupId> <artifactId>my-maven-plugi…

腾讯云服务器优惠活动大全页面_全站搜优惠合集

腾讯云推出优惠全站搜页面 https://curl.qcloud.com/PPrF9NFe 在这个页面可以一键查询所需云服务器、轻量应用服务器、数据库、存储、CDN、网络、安全、大数据等云产品优惠活动大全&#xff0c;活动打开如下图&#xff1a; 腾讯云优惠全站搜 腾讯云优惠全站搜页面 txybk.com/go…

springboot笔记

尚硅谷SpringBoot3零基础教程&#xff0c;springboot入门到实战_哔哩哔哩_bilibili SpringBOOT 只会扫描在主程序下的包!!!!!!!!!!!!写在其他包上面会有问题 //SpringBootApplication(scanBasePackages "com") //也可以自己设置扫描路径 &#xff33;&#xff50…

【Qt开发流程】之UDP

概述 UDP (User Datagram Protocol)是一种简单的传输层协议。与TCP不同&#xff0c;UDP不提供可靠的数据传输和错误检测机制。UDP主要用于那些对实时性要求较高、对数据传输可靠性要求较低的应用&#xff0c;如音频、视频、实时游戏等。 UDP使用无连接的数据报传输模式。在传…

白日门引擎传奇手游架设教程-GM的成长之路

准备工具 服务器一台&#xff08;Windows系统&#xff09;白日门引擎服务端版本一个 前言&#xff1a; 此次教程使用的是版本是一个决战斗罗的一个版本、服务器使用的是驰网科技的游戏高频系列服务器。 教程开始 在我们拿到版本之后、我们需要先把版本解压到服务器D盘的根目录…

Mac安装Typora实现markdown自由

一、什么是markdown Markdown 是一种轻量级标记语言&#xff0c;创始人为约翰格鲁伯&#xff08;John Gruber&#xff09;。 它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然后转换成有效的 XHTML&#xff08;或者HTML&#xff09;文档。这种语言吸收了很多在电子邮…

RocketMQ系统性学习-SpringCloud Alibaba集成RocketMQ以及顺序消费实战

顺序消费实战 顺序消费分为两种&#xff1a; 全局有序&#xff1a;适用于并发度不大&#xff0c;并且对消息要求严格一致性的场景下 通过创建一个 topic&#xff0c;并且该 topic 下只有一个队列&#xff0c;那么生产者向着一个队列中发消息&#xff0c;消费者也在这一个队列中…

Redis-数据结构

参考资料 极客时间Redis&#xff08;亚风&#xff09; Redis数据结构 SDS sds(Simple Dynamic String) 字符串接结构体: struct --attribute_- ((-_packed__)) sdshdr8{uint8_t len&#xff1b;/* buf已保祥的字符串字节数&#xff0c;不包含结束标示*/uint8_t alloc&#…

正式开通运营!“一应黔行”服务网点进驻贵阳地铁3号线

今天下午14:00&#xff0c;贵阳地铁3号线正式进入初期运营。为进一步实现一卡通在贵阳市全区域覆盖&#xff0c;不断提升“一应黔行一卡通”业务办理效率&#xff0c;贵阳市信捷科技有限公司在贵阳地铁3号线明珠大道站、顺海站、皂角井站3个站点设立“一应黔行”服务网点&#…

[Spring ~松耦合的设计神器]`SPI`

Java SPI&#xff08;Service Provider Interface&#xff09;是一种Java的服务提供者接口机制。它允许在运行时动态加载实现服务接口的类。 文章目录 基本概念最简单的实例使用 jar 包通过 spi动态实现接口功能 基本概念 SPI 机制的基本思想是&#xff0c;定义一个服务接口&a…

基于ssm线上学习网站论文

线上学习网站 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;作为学校以及一些培训机构&#xff0c;都在用信息化战术来部署线上学习以及线上考试&#xff0c;可以与线下的考试有机的结合在一起&#xff0c;实现线上学习网站在技术上已成熟。本文介绍了线上学…

【Android开发-25】Android中多线程编程用法介绍

1&#xff0c;线程基本用法 在Android中&#xff0c;线程的使用主要有两种方法&#xff1a;一种是扩展java.lang.Thread类&#xff0c;另一种是实现Runnable接口。 1.1以下是一个简单的Android线程继承Thread的用法示例&#xff1a; public class MyThread extends Thread {…

maven+spock

pom配置 话说JunitMockito的组合用起来是真难用&#xff0c;还是Spock的简单&#xff0c;尤其是参数化的测试。junit的Parameter是鸡肋&#xff0c;杂恶心&#xff1b;Theories用来也不爽。 <?xml version"1.0" encoding"UTF-8"?><project xm…