返回
巧用指针,两数相加化繁为简!
后端
2024-01-02 07:55:43
两数相加:使用指针巧妙解决链表相加问题
了解两数相加
当我们面临两个链表,需要对它们进行相加运算时,我们不能直接用小学算术的方法来进行计算,因为链表的存储方式是逆序的。为了解决这个问题,我们需要使用一种巧妙的方法来处理这种逆序存储的数字。
指针的妙用
为了解决链表相加问题,我们可以使用指针来巧妙地遍历和相加链表中的数字。指针是一种变量,它可以存储另一个变量的内存地址。通过使用指针,我们可以轻松地遍历链表,并访问和修改其中的元素。
算法步骤
使用指针解决两数相加问题的具体步骤如下:
- 创建哑结点: 创建一个新的链表,作为结果链表的哑结点。
- 初始化指针: 分别将两个输入链表的头指针命名为 "l1" 和 "l2"。
- 初始化进位变量: 初始化一个变量 "carry" 为 0,表示是否有进位。
- 循环相加:
- 遍历两个链表,同时比较 "l1" 和 "l2" 的当前值。
- 计算两个当前值的和并加上进位 "carry"。
- 更新进位 "carry" 为结果除以 10 的余数。
- 创建一个新的节点,值为结果模 10,并将其添加到结果链表中。
- 处理进位:
- 如果两个链表都遍历完了,但仍有进位 "carry",则创建一个新的节点,值为 "carry",并将其添加到结果链表中。
- 返回结果: 返回结果链表的下一个节点,它代表了相加结果。
代码示例
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" 替换为任意数量的链表变量即可。