首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

LeetCode题集-2 - 两数相加

这个题目是什么意思呢?简单来说就是把两个链表平铺开,头节点对齐,然后从头开始相同的节点相加,满10则进位,进位值与下个节点继续相加,当一个链表没有节点时候则可以把没有节点当做0继续与有节点的链表继续相加。具体示例如下:

到这里不知道你是否已经有解题思路了呢?

解法一:递归法

我第一反应就是递归,为什么?想想题目,对两个链表相同节点位置值按顺序求值,第一个算完算第二个,以此类推直至所有节点计算完成,这不正好使用递归吗,定义一个方法计算两个节点和,然后以头节点的下个节点作为递归点,即计算头节点后,头节点的下个节点计算直接调用自身方法直至所有节点计算完成,具体代码如下:

public static ListNode AddTwoNumbersRecursion(ListNode l1, ListNode l2)

{

return AddTwoNumbersRecursive(l1, l2, 0);

}

private static ListNode AddTwoNumbersRecursive(ListNode l1, ListNode l2, int carry)

{

//当两个链表节点都为空并且进位值等于0,则结束递归

if (l1 == null && l2 == null && carry == 0)

{

return null;

}

//以进位值为初始值定义两节点和变量,

var sum = carry;

//如果l1节点不为空,则累加其节点值,并且把其下个节点赋值给自身,用于下次迭代

if (l1 != null)

{

sum += l1.val;

l1 = l1.next;

}

//如果l2节点不为空,则累加其节点值,并且把其下个节点赋值给自身,用于下次迭代

if (l2 != null)

{

sum += l2.val;

l2 = l2.next;

}

//计算进位值

carry = sum / 10;

//以当前位值,创建下一个节点

return new ListNode(sum % 10)

{

//递归点

next = AddTwoNumbersRecursive(l1, l2, carry)

};

}

然后我们运行代码验证一下,结果如下:

解法二:迭代法

我们知道因为每次递归都会需要额外的栈空间,因此深度递归可能会引发一系列性能问题,因此我们是否还有其他办法呢?

递归有个同义词叫迭代,而迭代只需要在一个循环里重复执行一个计算即可,这样就可以避免递归产生的问题。

因此我们只需要把递归方法改造成迭代方法即可,里面的解题思路基本都是一样的,只不过是不通的写法。代码如下:

public static ListNode AddTwoNumbersIteration(ListNode l1, ListNode l2)

{

//创建头节点,即第一位计算结果

var head = new ListNode(0);

//用于迭代节点

var current = head;

//初始化进位值

int carry = 0;

//当两个链表节点都不为空并且进位值不等于0,则继续迭代

while (l1 != null || l2 != null || carry != 0)

{

//以进位值为初始值定义两节点和变量,

var sum = carry;

//如果l1节点不为空,则累加其节点值,并且把其下个节点赋值给自身,用于下次迭代

if (l1 != null)

{

sum += l1.val;

l1 = l1.next;

}

//如果l2节点不为空,则累加其节点值,并且把其下个节点赋值给自身,用于下次迭代

if (l2 != null)

{

sum += l2.val;

l2 = l2.next;

}

//计算进位值

carry = sum / 10;

//以当前位值,创建下一个节点

current.next = new ListNode(sum % 10);

//把下个节点赋值给当前迭代节点,继续下次迭代

current = current.next;

}

//返回实际结果链表的头节点

return head.next;

}

运行结果如下:

对于这一题核心解题思路是一样,问题在于如何选择方法,递归有递归的好处,迭代有迭代的好处,因此要根据自己实际情况进行选择。

下面对递归和迭代做个点单对比:

递归:代码更简洁直观,逻辑更接近问题的自然描述易于理解;但是递归会消耗更多内存,深度递归可能会导致栈溢出。

迭代:节省内存,性能会更好;但是代码更难理解。

题目到这里就做完了,但是不知道有没有人会有这样的疑惑?

在迭代法中,链表head是一个引用类型,并且被赋值给了链表current,而链表current在迭代中不停的被current.next覆盖,那么为什么这个覆盖过程没有影响到链表head?导致head为整个链表的最后一个节点?最后返回的head.next还是正确的答案?

你知道为什么吗?

:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O8CMBo7kG5N4rMiu0xhrF3kg0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券