【力扣2】两数相加

Posted by Hilda on September 11, 2025

2. 两数相加

首先,通过 listLen(ListNode l) 方法分别计算出两个链表 l1l2 的长度。然后,它根据长度比较,将较长的链表赋给 l (long),将较短的链表赋给 s (short)。这么做是为了后续的加法操作能直接在较长的链表上进行修改,而不需要创建新的节点来存储结果(除了可能出现的最后一位进位)。

然后开始遍历链表,分为下面3个阶段:

  • 同时遍历长短链表:计算当前两个节点的值以及上一位的进位 carry 的和:curNum = l.val + s.val + carry。计算新的进位:carry = curNum / 10。将当前位的结果(个位数)存回较长的链表节点:l.val = curNum % 10。更新 last 节点,以便在循环结束后能够处理可能的最后进位。将 l 和 s 分别移动到下一个节点。这个循环会一直运行,直到较短的链表 s 遍历完毕。
  • 处理长链表(此时短链表已经遍历完):当短链表 s 遍历结束后,长链表 l 可能还有剩余的节点。使用第二个 while 循环来处理这些剩余节点。它只将每个节点的值与 carry 相加,并更新进位和当前节点的值。这个循环确保了即使两个链表的长度不同,加法操作也能正确地从低位(链表头部)一直延伸到高位(链表尾部)。
  • 处理最后的进位:如果两个链表的所有节点都处理完毕后,carry 的值仍然不为零(例如,5 -> 95 相加,结果是 0 -> 0 -> 1),这意味着需要新增一个节点来存储这个进位。通过 if (carry != 0) 判断是否存在进位,如果存在,则在上一个处理的节点 last 的末尾添加一个新的节点,其值为 1

最后,代码返回 head,即较长链表的头节点。因为所有的加法操作都是在较长链表上进行的,这个链表现在已经包含了最终的和。

这种原地修改的思路避免了创建大量新节点的开销,是解决这类链表问题的常见策略之一。

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
49
50
51
52
53
54
55
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        // 分出链表哪个长,哪个短
        int len1 = listLen(l1);
        int len2 = listLen(l2);
        ListNode l = len1 >= len2 ? l1 : l2;
        ListNode head = l;
        ListNode s = head == l1 ? l2 : l1;
        ListNode last = l;
        int curNum = 0;
        int carry = 0;
        // 两个都还有
        while (l != null && s != null) {
            curNum = l.val + s.val + carry;
            carry = curNum / 10;
            l.val = curNum % 10;
            last = l;
            l = l.next;
            s = s.next;
        }

        // 长的还有
        while (l != null) {
            curNum = l.val + carry;
            carry = curNum / 10;
            l.val = curNum % 10;
            last = l;
            l = l.next;
        }
        // carry还有
        if (carry != 0) {
            last.next = new ListNode(1);
        }
        return head;
    }

    public int listLen(ListNode l) {
        int ans = 0;
        while (l != null) {
            ans++;
            l = l.next;
        }
        return ans;
    }
}