问题描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
个人初见解题思路
理解完题目要求后,本人产生了两种解题思路。
第一种:
将两个链表转成数字,相加求和,再将和转链表输出。
第二种:
按加法计算公式,每位相加。
第一种实现起来简单,但是有缺点,一旦链表长度超过语言能承受的最大数字长度,就万策尽了。
第二种方式可以解决第一种的问题,但是实现起来没有第一种简单。
先按照第一种方法来实现
public class Solution {
public ListNode AddTwoNumbers(ListNode l1, ListNode l2){
return NumToListNodeDesc(ListNodeToNum(l1) + ListNodeToNum(l2));
}
public long ListNodeToNum(ListNode<int> node)
{
var numStr = "";
var currentNode = node;
while (currentNode != null)
{
numStr = $"{currentNode.val}{numStr}";
currentNode = currentNode.next;
}
return long.Parse(numStr);
}
public ListNode<int> NumToListNodeDesc(long num)
{
var numStr = num.ToString();
ListNode<int> beforeNode = null;
for (int i = 0; i <= numStr.Length - 1; i++)
{
var numVal = int.Parse(numStr[i].ToString());
var node = new ListNode<int>(numVal, beforeNode);
beforeNode = node;
}
return beforeNode;
}
}
运行测试之后,长度短的链表没有问题,但是提交解题答案时候,不知道被多少亿的数值打爆了
所以,我们还得采用第二种解决方案
代码计算两数相加
在构思第二种解题思路的时候,突然发现,题目给的是逆序进来,要的返回结果,也是逆序出去,所以我们在计算的时候,其实没有必要去特意的把数字颠倒过来,因为 243 + 564 = 708,和预期链表结果708是一致的顺序,所以,题目本身的逆序就是烟雾弹。
加法思路:
我们需要从头开始遍历两个链表,把当前节点加起来求和,如果和大于10,下一次两个节点求和需要+1,如果遍历过程中有一个链表已经是空了,那么求和的时候把这个链表的值当0即可,另外的,还需要在整个链表遍历完成后,检查最后求和结果有没有超过10,如果超过了,还需要往前补1。
记录加法结果:
最初想的思路是在遍历列表的时候,建立一个List存储结果,链表遍历完成后,再List转链表,后面想了下,其实可以直接在求和的时候 ,通过移动当前node节点指针的方式,同步记录结果,不过这样需要注意的是,需要建立头部空节点,否则头部指针就丢失了。
最终实现如下:
public class Solution {
public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
var l1Access = l1;
var l2Access = l2;
var pre = new ListNode();
var cur = pre;
var overflow = 0;
while (l1Access != null || l2Access != null)
{
var addRsp = (l1Access != null ? l1Access.val : 0) + (l2Access != null ? l2Access.val : 0) + overflow;
overflow = addRsp / 10;
cur.next = new ListNode(addRsp % 10);
cur = cur.next;
if (l1Access != null)
{
l1Access = l1Access.next;
}
if (l2Access != null)
{
l2Access = l2Access.next;
}
}
if (overflow > 0)
{
cur.next = new ListNode(overflow);
}
return pre.next;
}
}
提交运行,没有问题。