LeetCode第二题:两数相加(Java)

简介: LeetCode第二题:两数相加(Java)

前言


面对困难,许多人望而却步,而成功的人士往往非常清楚,只要敢于和困难拼搏一番,就会发现,困难不过如此!

一、题目内容


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

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

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

image.png

示例1:

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

输出:[7,0,8]

解释: 342 + 465 = 807

示例2:

输入: l1 = [0], l2 = [0]

输出: [0]

示例3:

输入: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]

输出: [8,9,9,9,0,0,0,1]

提示:

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

代码实例

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/classSolution {
publicListNodeaddTwoNumbers(ListNodel1, ListNodel2) {
    }
}

二、解题过程


在看到这道题时,第一想法是逐个遍历链表的节点,将每个节点的数据取出并存储到String类型的数据中,再将这些String类型的字符数数据拼接起来反转后再成int类型的数据。之后夭折在了错误的思路上,后面看了相关的解答之后才明白,可以定义一条新的链表按节点来逐个存储两条链表相加的值,最后将这条新的链表返回。

1. 解题思路


image.png

创建一条新的链表,设置两个头指针current和result,在两条链表相加的过程中只移动current指针,result指针不移动,最后将result返回。两条链表节点的值在相加时会有进位的情况,因此要进位的数与不进位的数(即剩余的数)进行获取和存储,因此再定义用来存储需要进位的int类型的变量total和存储不需要进位的数值的int类型变量remainder,将两个变量的初值均定义为0。

对两条链表进行遍历,判断条件为当两条链表同时为空时结束循环,确保遍历到了每一条链表的每一个节点。获取需要进位与不需要进位的数值的方法为将两个链表对应节点相加后的值与10进行整除和取余操作,整除后的结果为需要进位的数,取余留下来的数据为不需要进位的数,因此在每一次求和时都会有三个数来相加(即两个链表对应的值和需要进位的数),需要进位的数初值为0,首次参与相加不会对结果产生影响。

将两个链表对应节点值分别存储到int类型数据中是因为如果在相加的过程中有一个链表为空的话就无法进行之后的相加,因此进行求和前先将两个链表的节点值存储到int类型数据中,在存储前进行当前节点是否为空的判断,如果当前节点不为空的话就将当前节点存储的值赋给int类型的数据,如果为空则将int类型的数据赋值为0。

在得到要进位的值total和不需要进位的值remainder后,首先进行新链表是否为空的判断(因为result不进行指针的移动,所以只对result进行非空判断即可),如果此时新链表为空的话,就将不需要进位的值remainder作为链表的含参构造对新链表进行初始化,此时新链表的头节点中存储的数据为不需要进位的值remainder,这样做的原因是为了防止最后返回的链表的头节点中存储着不需要的数据,在之后的判断中都不会再进入新链表为空的执行代码中,因此每一次只需要将不需要进位的值作为链表的含参构造的参数创建新的节点,确保当前节点中存储的值是不需要进位的值 remainder,所以需要进位的值total只参与求和的运算,而不需要进位的值remainder进行的是新链表节点的构造。最后将current指针向后移动,确保此时current指向的节点为null

在相加与存储到新链表的过程结束后,对链表L1和L2分别进行非空的判断,当L1和L2不为空时向后移动。如果不进行非空的判断,假设L1此时为null,再进行移动时会报空指针异常。

循环结束后,两个链表的节点都进行了相加,但是此时新链表的构造是用不需要进位的值remainder构造的,节点最后一次相加的结果如果需要进位的话这个时候最后一个值是没有存储到新链表当中的,因此需要在循环结束后再对需要进位的值total与0进行一次比较,如果大于0的话表示需要进位,则用total的值做为参数进行节点的含参构造,将最后一个值存储到新链表当中,如果total的值小于0则表明不存在还没有要添加到新链表当中的数据,此时将新链表result返回即可(current永远指向链表的下一个节点,永远为null,因此不将current返回)。

2. 解题代码


代码如下(示例):

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/classSolution {
publicListNodeaddTwoNumbers(ListNodel1, ListNodel2) {
// 定义一个链表用来存储两条链表相加的结果,result和current为两个指针// current为头结点不进行移动,result为最后要输出的链表ListNoderesult=null, current=null;
// 定义total变量为l1和l2两条链表相加后需要进位的数据inttotal=0;
// 如果l1和l2两条链表相加后需要进位,remainder变量为个位数的值// 如果l1和l2两条链表相加后不需要进位,remainder为两数相加后的值intremainder=0;
// 只要有一条链表不为空就继续进行遍历while (l1!=null||l2!=null) {
intnum1=l1!=null?l1.val : 0;
intnum2=l2!=null?l2.val : 0;
// 定义sum为两数相加后再与进位数相加后的值intsum=num1+num2+total;
// 对两数相加的结果进行整除,取出进位的值total=sum/10;
// 对两数相加的结果对10进行取余,取出不需要进位的值remainder=sum%10;
if (result==null) {
result=current=newListNode(remainder);
            } else {
// 将当前不需要进位的值赋值给下一个节点要存储的值current.next=newListNode(remainder);
// 将current指针向后移动current=current.next;
            }
// 将l1和l2节点同时向后移动if (l1!=null) {
l1=l1.next;
            }
if (l2!=null) {
l2=l2.next;
            }
        }
if (total>0) {
current.next=newListNode(total);
        }
returnresult;
    }
}

三、提交结果


image.png

总结


以上便是LeetCode第二道题两数相加的解题思路和过程,在解题的过程中我认识到了要灵活的利用链表的特性而不是一味的使用最笨拙的办法去求解,可以转换思路,尝试构造一个新的相同的对象来进行求解。

真正成功的人生,不在于成就的大小,而在于你是否努力地去实现自我,喊出自己的声音,走出属于自己的道路!

image.png

image.png

相关文章
|
27天前
|
算法 Java
LeetCode(一)Java
LeetCode(一)Java
|
3月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
49 6
|
3月前
|
存储 算法 Java
LeetCode经典算法题:打家劫舍java详解
LeetCode经典算法题:打家劫舍java详解
65 2
|
3月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
48 1
|
3月前
|
存储 算法 Java
LeetCode经典算法题:预测赢家+香槟塔java解法
LeetCode经典算法题:预测赢家+香槟塔java解法
50 1
|
3月前
|
存储 算法 Java
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
LeetCode经典算法题:二叉树遍历(递归遍历+迭代遍历+层序遍历)以及线索二叉树java详解
76 0
|
3月前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
53 0
|
9天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
80 38
|
6天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
1天前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
12 4