题目:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
上面就是力扣的原题,想必进过力扣的都应该遇到过了吧
这里共有两种解法
咋们先说第一种解法,迭代法
迭代法
迭代法,顾名思义就是利用循环遍历来进行解题
我大概说一下我的思路:
每个节点相加后,只会在新的节点中加入相加总数的个位,如果相加的总数大于等于了10的话,就会向前进一,给新节点的下一个节点加一,那么我们可以定一个新的变量next1来存储相加总和大于了10的十位,也就是需要进的位,然后每次相加时都把这个需要进的位加上,如果没有需要进的位,那么next1也就为0。
定义行链表的时候,我们可以把第一个节点设置为‘哨兵节点’,也就是不使用它,好进行操作,最后返回它的下一个节点就行,这个方法在解好多算法题都有效,下面我来图示一下(这个与题给的数字有差别,但不影响,这个更好):
第一次 2 + 5 = 7,那么存入链表的就是 总数%10 的数,在加上需要进位的数,即 7%10+next1=7
进行完一次后指针要后移
第二次4+6=10,大于等于10,只要往链表中加入个位,也就是取余10得到0,且next1,需要进的位也变成了1
此时,第三次加入的时候,总数为9,但需要加上上一次进的位,所有总数又大于等于了10,又需要往后进一位
但此时,链表都遍历完毕,但需要进的位中还有一个,这时就直接把需要进的位直接加入链表即可
最后就这直接返回res.next即可
Java代码如下:
这里ListNode力扣中已经给出,这里就不再解释了
/**
* 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) {
int total = 0;//定义总和
int next1 = 0;//是否向下一位进1
ListNode res = new ListNode(); //定义返回的结果
ListNode cur = res; //定义当前指针的位置,初始指向开头
while(l1 != null && l2 != null){ //两个链表都不是空时
total = l1.val + l2.val + next1;
cur.next = new ListNode(total % 10);//存入个位
next1 = total / 10;//计算出下一位要进的数
l1 = l1.next; //链表的下一个
l2 = l2.next; //链表的下一个
cur = cur.next; //当前指针下移
}
while(l1 != null){
total = l1.val + next1;
cur.next = new ListNode(total % 10);//存入个位
next1 = total / 10;//计算出下一位要进的数
l1 = l1.next;
cur = cur.next; //当前指针下移
}
while(l2 != null){
total = l2.val + next1;
cur.next = new ListNode(total % 10);//存入个位
next1 = total / 10;//计算出下一位要进的数
l2 = l2.next;
cur = cur.next; //当前指针下移
}
if(next1 != 0){
cur.next = new ListNode(next1);//存入个位
}
return res.next;
}
}
递归调用法
递归调用法,就是每次加完后就把需要加的位,加入到原链表下一次需要加的数据身上,方便下一次递归调用可以取到数据,如果当一个链表走完之后就创建一个0数据的放入原链表,好进行下一次递归,每次数据处理完毕后,就再一次调用此方法,在调用之前一定要记住把两个链表进行指针后移。
下面我图示说明一下
这里total,next1我就不再解释他的用法,和怎么加入算出next1的
方法执行完毕之后,指针下移,并进行递归调用
下一次递归时,L1的下一个节点数据已经变为了4,
当后面没数据,且需要进的位也为0是,就结束递归
下面,我按照上面的步骤,演示一下,当链表结束后,需要进的位还有数据怎么办
若此时,链表已经结束,但需要进的位中还有数据,就把给链表创建一个新的节点,然后把需要进的位加入到链表中
下一次递归直接进行相加即可,这里有人可能要问了,为什么刚才不直接把next1加入到链表呢?
因为next1这里是临时变量,当进行下一次递归调用时,就无法获取到,上一次递归调用的数据,如果直接加入的话,会导致每次都会把next1加入到链表中。
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) {
int total = 0;//定义总和
int next1 = 0;//是否向下一位进1
ListNode res = new ListNode(); //定义返回的结果
total = l1.val + l2.val; //加总数
next1 = total / 10; //获取要进的数
res = new ListNode(total % 10);//把总数的个位存入链表
if(l1.next != null || l2.next != null || next1 != 0 ){
if(l1.next != null){ //如果l1 不为null
l1 = l1.next; //指针后移
}else{
l1 = new ListNode(0); //创建一个新的为0的节点
}
if(l2.next != null){ //如果l2 不为null
l2 = l2.next; //指针后移
}else{
l2 = new ListNode(0); //创建一个新的为0的节点
}
l1.val = l1.val + next1; //把需要进的位随意加到 l1/l2 上,方便下次递归能找到
res.next = addTwoNumbers(l1,l2); //进行递归,此时l1 l2已经变换
}
return res;
}
}
制作不易,记得点赞!!!