【LeetCode-中等-链表】两数相加
这是个关于链表的题目, 以前在C#中写代码时,对链表接触比较少,所以刚好接这个题目来更好的熟悉一下链表
题目大概是这样的,给你两个非空的链表,表示两个非负的整数. 它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字 =》 首先我们来理解这句话是什么意思
我们来看一个链表 1->5->9 看这个链表,有三个节点,每个节点都分别存储了一位数字,第1个节点存储1,指向的是第2个节点(第2个节点存储5),第2个节点指向的是第3个节点(第3个节点存储的是9), 显然这个链表是非空的(非空链表), 满足上面的要求,在看上面一句话 “表示两个非负的整数,它们每位数字都是按照逆序的方式存储的” =》 这句话的啥意思呢,也就是说这个链表是用来表示一个整数的,并且这个整数在链表中是按照逆序的方式存储的,也就是说它表示的这个整数是951,如果是安装链表的指向顺序方式存储就应该是159, 因为是1指向5,5指向9, 现在题目说了每位数字都是按照逆序方式存储的,所以肯定是反过来,也就是951
现在题目要求是这样的:
给你两个非空的链表,表示两个非负的整数. 它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。 要求你把这两个数相加,并以相同的形式返回一个表示和的链表。
比如 第1个链表 1->7->5 第2个链表 3->5->2 那么第1个链表表示的数字是571 第2个链表表示的数字是253 那么这两个数相加 571 + 253 = 824
所以这个链表表示的是 4->2->8
两个链表也有可能长度不同,比如第1个链表 1->7->4->3->8 第2个链表 3->5->2 那么第1个链表表示的数字是 83471 第2个链表表示的数字是253 那么和是 83471 + 253 = 83724 => 这里要有数学思维,我们用m来表示第1个链表的节点的值,n来表示第2个链表的节点的值
第1个节点: m = 1, n = 3, m + n = 1+3 = 4
第2个节点: m = 7, n =5, m + n = 7+5 =12 => 这个节点怎么放呢 节点处存放的值为 (7+5) % 10 = 2 这个节点放的是两个节点值的和除以10的余数(英文中这个单词叫 mod),而进位呢 进位 = (7 + 5) / 10 = 1, 这里英文中我们把进位叫carry, 进位carry是要加到下一个节点中去的, 所以下一个节点的值是 (m + n + carry) % 10
第3个节点: m = 4, n = 2,还有上一个节点过来的进位carry = 1, 所以 m + n + carry = 4 + 2 + 1 = 7, 节点处存放的值是 (m + n + carry) % 10 = 7
看明白了么,每个节点存放的值都可以说是 (m+n+carry) % 10, 每个节点产生的进位(进位carry是要加到下一个节点中的)是 (m+n+carry) / 10
显然,如果最后一个节点产生的进位carry > 0, 那么它也要加入到下一个节点中,也就是说在最后一个节点后面,会产生一个新的节点,节点的值为最后一个节点产生的carry. 现在我们再来看这个例子
第1个链表 1 -> 7 -> 4->3->8 每个节点的值用m来表示
第2个链表 3->5->2 每个节点的值用n来表示
第1个节点: m = 1, n = 3, 初始化carry = 0, 节点存放的值 (m + n + carry) % 10 = 4, 该节点产生的进位 carry = (m + n + carry) / 10 = 0
第2个节点: m = 7, n = 5, 来自第1个节点的carry = 0, 所以 节点存放的值为 (7 + 5 + 0) % 10 = 2, 该节点产生的进位 carry = (7+5+0) / 10 = 1
第3个节点: m = 4, n = 2, 来自第2个节点的carry = 1, 所以节点存放的值为 (4 + 2 + 1) % 10 = 7, 该节点产生的进位 carry = (4 + 2 + 1) / 10 = 0
第4个节点: m = 3, n= 0 (第2个链表没有第4个节点了,所以n=0), 来自第3个节点的进位carry = 0, 所以节点存放的值为 ( 3 + 0 + 0) % 10 = 3, 该节点产生的进位carry = (3 + 0 + 0 ) / 10 = 0
第5个节点: m = 8, n =0,来自第4个节点的进位carry=0, 所以节点存放的值为 (8 + 0 + 0) % 10 = 8, 该节点产生的进位carry = (8 + 0 + 0) / 10 = 0
所以这个结果链表表示的是 4->2->7->3->8
现在我们来写代码,解这道题,我们首先要建立一个单链表的类,在C#里面,它是这样的:
public class ListNode {
public int Val;
public ListNode Next;
public ListNode(int val = 0, ListNode next = null)
{
Val = val;
Next = next;
}
}
public class SumofTwoListNode(ListNode node1, ListNode node2)
{
ListNode head = null; //结果链表的头节点
ListNode tail = null; //结果链表的尾节点
int carry = 0; //初始化进位为0 我刚开始写代码时,把这句写在while循环里面,发现行不通,因为这样,每次循环开始,它都是0,无法更新进位值,所以我们要跳出思维框框,把它的初始化放在while循环外面
while(node1 != null || node2 != null)
{
int node1Value = node1 != null ? node1.Val : 0;
int node2Value = node2 != null ? node2.Val : 0;
// int carry = 0// 刚开始把初始化进位放在这里,发现行不通
resultNodeValue = (node1Value + node2Value + carry) % 10;
carry = (node1Value + node2Value + carry) / 10; //该节点产生的新进位
if(head = null) //产生结果链表的第一个节点
{
head = tail = new ListNode(resultNodeValue); //产生的结果链表中的第1个节点,同时作为头节点,也同时作为尾节点
}
else //结果链表中已经有节点了
{
tail.next = new ListNode(resultNodeValue);
tail = tail.next;
}
if(node1 ! = null)
node1 = node1.next;
if(node2 != null)
node2 = node2.next
}
if(carry > 0) //循环完成后,carry还有值,表明需要新增一个节点,节点值为carry
{
tail.next = new ListNode(carry);
}
return head;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律