文章目录

  • 1:问题描述
  • 2:问题分析
  • 2.1 Python链表实现
  • 2.2 问题分析


1:问题描述

来源:LeetCode

难度:中等


问题详情:

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

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

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

示例1:

python 两个列表包含判断 python两个列表可以相加吗_leetcode

输入: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)