返回

巧用指针,两数相加化繁为简!

后端

两数相加:使用指针巧妙解决链表相加问题

了解两数相加

当我们面临两个链表,需要对它们进行相加运算时,我们不能直接用小学算术的方法来进行计算,因为链表的存储方式是逆序的。为了解决这个问题,我们需要使用一种巧妙的方法来处理这种逆序存储的数字。

指针的妙用

为了解决链表相加问题,我们可以使用指针来巧妙地遍历和相加链表中的数字。指针是一种变量,它可以存储另一个变量的内存地址。通过使用指针,我们可以轻松地遍历链表,并访问和修改其中的元素。

算法步骤

使用指针解决两数相加问题的具体步骤如下:

  1. 创建哑结点: 创建一个新的链表,作为结果链表的哑结点。
  2. 初始化指针: 分别将两个输入链表的头指针命名为 "l1" 和 "l2"。
  3. 初始化进位变量: 初始化一个变量 "carry" 为 0,表示是否有进位。
  4. 循环相加:
    • 遍历两个链表,同时比较 "l1" 和 "l2" 的当前值。
    • 计算两个当前值的和并加上进位 "carry"。
    • 更新进位 "carry" 为结果除以 10 的余数。
    • 创建一个新的节点,值为结果模 10,并将其添加到结果链表中。
  5. 处理进位:
    • 如果两个链表都遍历完了,但仍有进位 "carry",则创建一个新的节点,值为 "carry",并将其添加到结果链表中。
  6. 返回结果: 返回结果链表的下一个节点,它代表了相加结果。

代码示例

def addTwoNumbers(l1, l2):
    # 创建哑结点
    head = ListNode(0)

    # 初始化指针和进位
    carry = 0
    l1_curr = l1
    l2_curr = l2

    # 循环相加
    while l1_curr or l2_curr or carry:
        # 计算两个当前值的和和进位
        val1 = l1_curr.val if l1_curr else 0
        val2 = l2_curr.val if l2_curr else 0
        sum = val1 + val2 + carry

        # 更新进位
        carry = sum // 10

        # 创建新节点并添加到结果链表
        new_node = ListNode(sum % 10)
        head.next = new_node
        head = head.next

        # 移动指针
        l1_curr = l1_curr.next if l1_curr else None
        l2_curr = l2_curr.next if l2_curr else None

    # 返回结果
    return head.next

复杂度分析

  • 时间复杂度:O(max(m, n)),其中 m 和 n 分别为两个链表的长度。
  • 空间复杂度:O(max(m, n)),因为结果链表的最大长度为 max(m, n)。

常见问题解答

1. 为什么使用指针来解决这个问题?

指针允许我们轻松地遍历链表,并访问和修改其中的元素。它比使用索引或迭代器更有效率。

2. 进位变量 "carry" 是如何更新的?

进位变量 "carry" 更新为当前和与进位相加的结果除以 10 的余数。

3. 如果两个链表的长度不同怎么办?

如果两个链表的长度不同,我们可以在较短的链表的末尾添加虚拟的 0 节点。

4. 如何处理链表中可能有多个进位的情况?

该算法可以处理任何数量的进位,因为进位变量 "carry" 会在每次迭代中更新。

5. 该算法可以推广到任意数量的链表相加吗?

是的,该算法可以推广到任意数量的链表相加,只需将代码中的 "l1" 和 "l2" 替换为任意数量的链表变量即可。