• 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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    按照提示简单实现一下:

    class ListNode(object):
        def __init__(self, val=0, next=None):
            self.val = val
            self.next = next
    
    ef 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    看一下上述代码的思路,首先构造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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

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

  • 相关阅读:
    基于采用哈代-温伯格均衡和交叉指数的随机交配的进化配接算法(EMA)(Matlab代码实现)
    [架构之路-17]:目标系统 - 硬件平台 - ARM CPU架构与系列选型
    Spring Boot——yml和properties详解
    毛玻璃 has 选择器卡片悬停效果
    如果一个人不爱你了,你只需拿回两样东西
    70、window11+visual studio2019+共享内存进行数据传输
    福建厦门航空飞机发动机零部件检测3D测量尺寸偏差比对-CASAIM中科广电
    模型选择、过拟合与欠拟合(多层感知机)
    计算机毕业设计Java教务系统(源码+系统+mysql数据库+lw文档)
    商城小程序?
  • 原文地址:https://blog.csdn.net/weixin_43490422/article/details/126310364