返回

LeetCode:算法入门题 - 两数相加,一步步带你啃

后端

两数相加:链表中的数字运算

1. 理解问题

在计算机科学中,链表是一种用于存储和组织数据的常用数据结构。它由一系列称为节点的元素组成,每个节点包含一个数据值和一个指向下一个节点的链接。当我们处理数字时,链表经常被用来表示非负整数,其中每个节点的值代表数字的某一位。

2. 挑战:两个链表相加

想象一下,你有两个使用链表存储的非负整数。你的任务是将这两个数字相加,并返回结果作为另一个链表。为了增加挑战,这些链表中的数字是逆序存储的,即最低有效位存储在头节点中。

3. 解题思路

乍一看,这个问题可能令人望而生畏,但我们可以将其分解为以下几个步骤:

  1. 初始化进位和结果链表: 开始时,我们设置进位为 0,并创建一个空结果链表头节点。
  2. 遍历链表,逐位相加: 从两个输入链表的头节点开始,我们逐个遍历并相加它们的对应节点值。如果相加结果大于或等于 10,我们将进位增加 1 并将结果减去 10。
  3. 处理链表长度不同: 如果两个链表的长度不同,我们将较短链表的剩余部分填充为 0。
  4. 处理进位: 遍历结束后,如果进位不为 0,我们将进位与结果链表的剩余部分相加。
  5. 反转结果链表: 由于数字是逆序存储的,我们必须反转最终结果链表以获得正确的数字表示。

4. 代码实现(Python)

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

def addTwoNumbers(l1, l2):
    """
    :type l1: ListNode
    :type l2: ListNode
    :rtype: ListNode
    """
    # 初始化进位和结果链表头节点
    carry = 0
    head = ListNode(0)
    # 指向结果链表头节点的下一个节点
    curr = head

    # 遍历两个链表,直到两个链表都为空
    while l1 or l2 or carry:
        # 计算两个链表当前节点的和和进位
        val1 = l1.val if l1 else 0
        val2 = l2.val if l2 else 0
        total = val1 + val2 + carry
        carry = total // 10
        # 将当前节点的和更新到结果链表
        curr.next = ListNode(total % 10)
        # 更新当前节点为下一个节点
        curr = curr.next
        # 更新两个链表的当前节点
        l1 = l1.next if l1 else None
        l2 = l2.next if l2 else None

    return head.next

5. 思考和总结

两数相加问题不仅测试了你对链表的基本操作的理解,还考验了你处理进位和不同链表长度的能力。通过解决这个问题,你可以磨练你的算法思维和数据结构技能。

常见问题解答

  1. 如何处理负数?
    此问题假设给定数字为非负数。如果需要处理负数,你需要修改算法以支持负数的表示和运算。

  2. 如何提高算法效率?
    为了提高算法的效率,可以采用分治或快速傅里叶变换等技术。

  3. 是否可以用递归来解决这个问题?
    是的,你可以使用递归来解决这个问题。只需从链表的头节点递归地遍历,并返回每个节点的相加结果和进位。

  4. 如何处理链表中的循环?
    如果链表中存在循环,则算法可能会陷入无限循环。为了防止这种情况,你需要使用哈希表或其他技巧来检测和处理循环。

  5. 有哪些替代方法可以相加两个数字?
    除了链表,还有其他数据结构可以用来表示数字,如数组、栈或队列。不同的数据结构可能有不同的相加算法。