前言
🎄:CSDN的小伙伴们大家好,今天跟大家分享一道经典的力扣启蒙题。如果这篇文章对你有用,麻烦给我点个小赞以示鼓励吧🎄
🏡:博客主页:空山新雨后的java知识图书馆
☔️:昨晚重庆挂大风,不知道各位小伙伴感受到了没有。
📝:不耻最后”。即使慢,弛而不息,纵会落后,纵会失败,但一定可以达到他所向的目标。——鲁迅📝
📖上一篇文章:Maven工具的使用📖
👏欢迎大家一起学习,进步。加油👊
力扣题的总结
题目描述,力扣第二题,算法启蒙
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/add-two-numbers/
实例
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
解题思路
1、首先先要弄懂题目的意思,题目是告诉我们两个链表,反序存储,也就是说,如果123+456,存进链表里面就是321+456,但是结果得是123+456=975;
2、首先我们解题的方法叫做迭代法
2.1、什么是迭代法?
迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。迭代算法是用计算机解决问题的一种基本方法,它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值,迭代法又分为精确迭代和近似迭代。比较典型的迭代法如“二分法”和"牛顿迭代法”属于近似迭代法。
3、那么我们可以采用迭代的方式,来完成这个题目,首先我们要明白,两数(均是个位数)相加,有两种结果,一种是小于10,不用进一,另一种结果是大于10.那么这种情况就要进一了。那么在本题中,由于是在链表中进行,因此我们需要一个变量来决定是否进一,我们定义为next1,还得有一个变量total来接收总数,因为我们的变量和实际存入链表中的值都是由这个total来决定的。
4、total = L1 + l2 和 可能存在的进一next1
next1 = total/10;
实际存入链表的值 = total%10
result结点和cur结点的关系,以及为啥要这么定义↓
5、定义好变量之后,我们要做的就是将两个链表分别进行遍历,直到有一方链表为空,就会去执行下面的代码,主要是检查两个链表单独的是否还存在没有被遍历完的情况, 以及最后相加的两个数可能大于10,那么就要进位,也得加上。
6、循环里面就应该算上total的值,以及他是否进位的值,以及实际存入链表的值,并将其存入链表,然后将所有的需要参与遍历的变量向后移动,保证循环继续,特别注意防止空指针的异常。
7、当其中有一条链表走完之后,就需要将剩余的一条链表进行遍历,注意的是,这时候的total值只剩下了其中一条链表的值和可能存在的进位值,因此不要加错了。
8、当所有的链表都遍历完之后,可能会存在一个进位值,切记要将这个进位值给加上。
9、最后返回链表即可。
图示
代码演示java
/**
* 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; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
//定义一个total,算的是l1,l2两个结点的和以及可能存在的进一
int total= 0;
//定义一个next,由total/10得到十位数,决定是否进一
int next1 = 0;
//定义一个新节点,作为首结点,首结点为空
ListNode result = new ListNode(0);
//定义一个current结点,用于存储最后的返回结果,返回result.next也就是最后的结果
ListNode cur = result;
//遍历两个链表,直到有一方为空截止
while(l1 != null || l2 != null) {
//考虑可能为空的情况存在,需要给赋值,防止空指针异常
int x = l1 == null ? 0 : l1.val;
int y = l2 == null ? 0 : l2.val;
//计算total
total = x + y + next1;
//current结点存的值应该是total的个位数的值
cur.next = new ListNode(total%10);
//那么next决定这进一,next的值就应该是十位数
next1 = total / 10;
//将l1,l2,cur依次向后移动
//注意为空的情况
if(l1 != null) {
l1 = l1.next;
}
if(l2!= null) {
l2 = l2.next;
}
cur = cur.next;
}
//当l2走完L1没走完的情况
while(l1 != null) {
total = l1.val + next1;
cur.next = new ListNode(total%10);
next1 = total / 10;
if(l1.next != null) {
l1 = l1.next;
}
cur = cur.next;
}
//当L1走完l2没走完的情况
while(l2 != null) {
total = l2.val + next1;
cur.next = new ListNode(total%10);
next1 = total / 10;
if(l2.next != null) {
l2 = l2.next;
}
cur = cur.next;
}
//当所有的结点都已经走完以后,需要判断一下是否还存在进一的数没有加进去
if(next1 != 0) {
cur.next = new ListNode(next1);
cur = cur.next;
}
return result.next;
}
}
结果
第二种解题方法:递归调用法
解题思路:
1、首先将l1.l2相加,得到了total值,这个total值我们取出他的个位数存入链表,将十位数作为进一的值,而且将它加到下一次递归调用的随便一个值的上面,参加下一次递归调用的运算,得到一个新的total,直到三个值都为空,为0,递归结束。那么这里面就只需要考虑到值为空的情况,如果链表为空,一定要赋值为0,否则他无法参加运算。
思路图示
代码java
/**
* 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; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
//定义total,首先就是两个值相加
int total = l1.val + l2.val;
//是否向下进一
int next1 = total/10;
//实际存入链表的值
ListNode res = new ListNode(total%10);
//当链表的值有一个不为空,或者向下进一不为0,都可以进入这个条件
if(l1.next != null || l2.next != null || next1 != 0) {
//这个判断是为了判断链表的下一个结点是否有值
if(l1.next != null) {
//如果有值,则向后移动
l1 = l1.next;
}else{
//如果没有值,则给他赋值为0
l1 = new ListNode(0);
}
if(l2.next != null) {
l2 = l2.next;
}else{
l2 = new ListNode(0);
}
//这里这样做的目的是为了将进一的值加到链表中去,
//具体加哪个链表,都可以
l1.val = l1.val + next1;
//递归调用该方法,这时候进去的l1,l2就是链表的下一位了,注意,next的值是被加进去了
res.next = addTwoNumbers(l1,l2);
}
//返回链表,直到递归结束,就得到了我们想要的结果。也就是l1,l2,next1的值都为0,就是我们最终想要的值了。
return res;
}
}