2. 两数相加

2. 两数相加 - 力扣(LeetCode)

class Solution {
public:
  ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    ListNode *Head = nullptr;
    ListNode *Prev = nullptr;
    ListNode *Ptr = nullptr;

    int Carry = 0;
    int Sum = 0;
    int Raw = 0;
    while (l1 || l2 || Carry) {
      if (l1) {
        Sum += l1->val;
        l1 = l1->next;
      }
      if (l2) {
        Sum += l2->val;
        l2 = l2->next;
      }
      Raw = Sum + Carry;
      Sum = Raw % 10;
      Carry = Raw / 10;

      Ptr = new ListNode(Sum);
      if (!Head)
        Head = Prev = Ptr;
      else
        Prev->next = Ptr;

      Prev = Ptr;
      Ptr = Ptr->next;
      Sum = 0;
    }

    return Head;
  }
};

这个还挺有意思的,你得考虑 l1、l2 的长度以及可能的进位,它们三个整体上是或的关系。

二刷

class Solution {
public:
  ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    int Sum = 0, Carry = 0;
    ListNode Dummy;
    ListNode *This = &Dummy;
    while (l1 || l2 || Carry) {
      int Primordial = Carry;
      if (l1) {
        Primordial += l1->val;
        l1 = l1->next;
      }
      if (l2) {
        Primordial += l2->val;
        l2 = l2->next;
      }
      Sum = Primordial % 10;
      This->next = new ListNode(Sum);
      This = This->next;
      Carry = Primordial / 10;
    }
    return Dummy.next;
  }
};

没什么好说的,注意终止条件和求进位的顺序就行。

三刷

class Solution {
public:
  ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    ListNode Pre, *Prev = &Pre;
    int Sum = 0;
    int Carry = 0;
    while (l1 || l2 || Carry) {
      int Raw = Carry;
      if (l1) {
        Raw += l1->val;
        l1 = l1->next;
      }
      if (l2) {
        Raw += l2->val;
        l2 = l2->next;
      }
      Sum = Raw % 10;
      Carry = Raw / 10;
      Prev->next = new ListNode(Sum);
      Prev = Prev->next;
    }
    return Pre.next;
  }
};

主要还是注意考虑两个表不一样长的情况——这强制我们在每次从l1和l2取数相加之前进行判断。此外两个表穷尽之后剩下的进位也要考虑。

进位写在最顶上的int Raw = Carry;的analogy是硬件加法器——在实际进行加法运算之前,先把上一次的进位传递过来。