LeetCode 第2题:两数相加(Python3解法)

1:问题描述

来源:LeetCode

难度:中等


问题详情:

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

示例1:
在这里插入图片描述

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]


2:问题分析

2.1 Python链表实现

链表按照逆序存储数值,输入中的l1= [2,4,3]实际表示的是342。存入链表后,则变成了2 -> 4 -> 3 -> None
在开始写解题代码前,先回顾下python如何实现链表形式,LeetCode已经给了提示。

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

按照提示简单实现一下:

class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def generate_ListNode(value_list: list) -> ListNode:
    """
    通过列表元素生成ListNode
    :param value_list:
    :return:
    """
    cur_node = None
    for item in value_list[::-1]:
        node = ListNode(item)
        node.next = cur_node
        cur_node = node
    return cur_node

l1_value = [2,4,3]
l2_value = [5,6,4]
l1 = generate_ListNode(l1_value)
l2 = generate_ListNode(l2_value)

看一下上述代码的思路,首先构造ListNode类,里面包含valnext 属性。

其次通过generate_ListNode类按照3->None, 4->3->None2->4->3->None的顺序构建l1。也就是说,构建链表是从右往左构建的。

2.2 问题分析

两个链表都是按照同样的逆序排列的,那么就只需要将链表对应位置相加并考虑进位即可。

但是需要考虑以下三种情况:

  1. 两个链表同长度,且相加后的值与二者仍旧同长度;e.g. 1 + 1 = 2
  2. 两个链表不同长度,且相加后的值与最长链表同长度;e.g. 19 + 1 = 20
  3. 相加后的值大于两个链表的长度,e.g. 91 + 9 = 100 或 9 + 1 = 10
  • 情况1,属于一般情况,只需要考虑进位即可;
  • 情况2,两个列表不同长度,则需要考虑对应位置两个链表是否存在None值;
  • 情况3,则需要考虑两个链表所有的元素遍历完后,最后的进位需要在循环外添加进去。

代码如下,详细解释在注释中提到。

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

# 需要考虑如下三种情况:
# 1:两个链表同长度,且相加后的值与二者仍旧同长度;e.g. 1 + 1 = 2
# 2:两个链表不同长度,且相加后的值与最长的那个链表同长度;e.g. 19 + 1 = 20
# 3:相加后的值大于两个链表的长度,e.g. 91 + 9 = 100 或 9 + 1 = 10
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """


        # 创建一个指针, head 和 end分别表示头指针和尾指针
        head = end = ListNode(-1)
        # 进位项
        carry = 0

        # 如果l1、l2、carry不全为None的话,进入循环
        # carry这个判断条件则是为了情况3,
        # 如果两个链表已经遍历完成,而carry还有进位,
        # 比如1+9=10,有一个进位1,则需要再进入循环
        while l1 or l2 or carry:
            total = 0
            # 解决情况2,如果当前链表不是None,则指针继续右移,
            # 否则跳过,None元素是没有next属性的,
            # 所以必须要判断。
            if l1:
                total += l1.val
                l1 = l1.next
            if l2:
                total += l2.val
                l2 = l2.next
            total += carry
            carry = total//10 # 计算进位
            end.next = ListNode(total%10) # 余数作为链表的当前值
            
            end = end.next
         # 头指针的下一个指针作为输出,因为尾部指针end已经到了链表的末尾,没法再回去了。
         # 所以只能返回头指针head.next,因为head目前的指向是没有意义的,只是为了初始化
         # 生成的一个元素,其下一个元素才是相加结果开始的地方。
        return head.next

假设最长的链表长度为n,则循环次数为n或者n+1,则时间复杂度为O(n)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

little student

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值