2 Add Two Numbers(两数相加)

版权申明:原创文章,未经博主同意,不得转载!
Add Two Numbers(两数相加),这是一道关于链表的题目,其内容如下:

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

可以看到这道题目并不困难,对于新手来说,解决的主要问题有两个,一在于链表数据类型的操作,这一点可能有的人比较陌生,二是对各种可能出现情况考虑的完备性,也就是算法是否能够通过各种特殊情况的测试。关于链表数据类型,感兴趣的同学可以点击链表

下面,我们简要的说明一下算法思路。

由于这道题目给定的数字顺序是从低位到高位的,这样就避免了顺序问题,而且每个结点只有一位非负整数。所以只需将两个链表中的元素逐位取出直接相加,考虑到进位情况,新链表对应位置存储个位数,设置进位标志参与下一位的运算,当结束后返回新链表就可以了。如下图给出的示例计算过程。

图片来源:leetcode-cn.com
具体的做法就是先建立一个新链表,保存新链表的头部用于返回,之后同步遍历给定的两个非空链表,在没有到达某一个链表最后一个结点之前,将两个链表的值相加,结果保留下来。这个题目的关键点在于对到达最后结点的链表如何处理。我们初步的思路是在两个链表都未到最后一个结点时,同步遍历计算结果。当一个链表到达最后结点后,结束同步遍历,仅对没有到达最后结点的链表进行处理。为了避免出现999…9 + 1这种连续进位的情况,在处理单链表是也需要保留进位。当处理完两个链表相加后,我们最后还需要处理最后一次相加的进位,因为两个十以内的数相加,带上进位最大也就是9+9+1 = 19这种情况,因此,进位非0即1,当进位为1时,在结果链表最后在建立一个结点保存,无进位就不用处理。我们的代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        # 创建新链表存储结果
        l3_start = ListNode(0)
        l3 = l3_start
        # 进位标志
        carry = 0
        # l1和l2都没有到最后一个结点
        while l1 and l2: 
            l3.next = ListNode((l1.val + l2.val + carry) % 10)
            carry = (l1.val + l2.val + carry) // 10
            # 取链表的下一个结点
            l1 = l1.next
            l2 = l2.next
            l3 = l3.next
        # l1没有到达最后一个结点
        if l1:
            # 只计算l1和进位
            while l1:
                l3.next = ListNode((l1.val + carry) % 10)
                carry = (l1.val + carry) // 10
                l1 = l1.next
                l3 = l3.next
        # l2没有到达最后一个结点
        if l2:
            # 只计算l2和进位
            while l2:
                l3.next = ListNode((l2.val + carry) % 10)
                carry = (l2.val + carry) // 10
                l2 = l2.next
                l3 = l3.next
        # 处理进位    
        if carry == 1:
            l3.next = ListNode(1)
        # 返回链表起点
        return l3_start.next

提交运行结果如下:

D:\工作号\文章\每日一练\02 addTwoSum\addTwoSum03.png
哈哈,结果还是可以的。

我们去看一下速度最快的代码是什么样子的。
在这里插入图片描述

后来看了官网给出的解答,这个代码的思路是按照如下思路写的:
https://leetcode-cn.com/problems/add-two-numbers/solution/liang-shu-xiang-jia-by-leetcode/
按照官方给定的伪代码,我们也编写了对应的代码。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        # 创建新链表存储结果
        l3_start = ListNode(0)
        l3 = l3_start
        # 进位标志
        carry = 0
        # l1和l2均为到达最后一个结点
        while l1 or l2: 
            # 到达最有一个结点的链表对应的数值赋为0
            x = l1.val if l1 else 0
            y = l2.val if l2 else 0
            # 计算和
            s = x + y + carry
            # 为新结点设定值
            l3.next = ListNode(s % 10)
            # 保留进位
            carry = s // 10
            # 指向下一个结点
            l3 = l3.next
            # 达最后一个结点的链表不在更新位置
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next  
        # 处理最后的进位
        if carry == 1:
            l3.next = ListNode(1)
        # 返回链表起点
        return l3_start.next

提交结果如下。
在这里插入图片描述

可以看到,运行速度还是很快的。

这道AddTwoSum的解法就介绍到这里。

以上。

本期到此结束,扫下面二维码加Python学习公众号,有海量优质学习资源!
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值