思路
同时遍历两个链表,直到两个都为nullptr。如果中途一个链表指针为空,则将其数字设置为0。
两数相加时维护一个进位变量carry,若相加之和≥10,则将carry设为1,否则为0。每次加法操作都由两数和carry共同相加。
p.s.虽然不喜欢数电课,但是进位变量确实是受加法器的启发。
代码
// 注意:不是最终正确版本
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int carry = 0; // 进位
ListNode* result = new ListNode(); // 结果链表
ListNode* p = result; // 循环指针
int n1, n2, temp;
// 都为空才退出循环
while (l1 != nullptr || l2 != nullptr) {
n1 = (l1 == nullptr ? 0 : l1->val);
n2 = (l2 == nullptr ? 0 : l2->val);
temp = n1 + n2 + carry;
if (temp < 10) {
carry = 0;
}
else {
temp -= 10;
carry = 1;
}
l1 = ( (l1->next == nullptr || l1 == nullptr) ? nullptr : l1->next);
l2 = ( (l2->next == nullptr || l2 == nullptr) ? nullptr : l2->next);
p->next = new ListNode(temp);
p = p->next;
}
// 最后一位还有进位则设为1
if (carry == 1)
p->next = new ListNode(1);
return result->next;
}
};
可惜报了RE的错误,经过检查发现是27行中l1->next == nullptr || l1 == nullptr
犯了一个小错误。
C++中条件表达式会从左往右依次判断,当一个为假时就不再执行后面的表达式了。因此如果l1本身已经是nullptr的话,l1->next
很明显就是一个非法的表达式,这里发生错误也就不会检查后面的l1了。所以修改如下: l1 == nullptr || l1->next == nullptr
就可以AC了。
但是尽管AC了,我发现这l1 == nullptr || l1->next == nullptr
句代码好像有些冗余,既然l1是nullptr的时候就已经将其设置为nullptr,那么就永远不会出现它的next还是nullptr了,因为它就没有next这个属性。
于是我将l1->next == nullptr
这个判断条件删去。虽然如我所愿简化了一点代码而且而AC了,但是耗时却增加了。
原因应该是提前一轮检测到了最后一个节点,节省了一次next的访问。