例题:
给定两个
非空
链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
进阶:
如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
示例:
输入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出: 7 -> 8 -> 0 -> 7
1. 使用C++引用传递,函数调用过程中修改的都是同一个地址空间中保存到carry值(进位值)
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int len1 = get_length(l1), len2 = get_length(l2);
int len = max(len1, len2);
if(len1 != len2){
ListNode* head = len1 < len2 ? l1 : l2;
for(int i = 0; i < len - min(len1, len2); i ++){
ListNode* node = new ListNode(0);
node->next = head;
head = node;
}
if(len1 < len2) l1 = head;
else l2 = head;
}
int carry = 0;
ListNode* res = go(l1, l2, carry);
if(carry){
ListNode* node = new ListNode(1);
node->next = res;
res = node;
}
return res;
}
private:
int get_length(ListNode* head){
if(!head) return 0;
return 1 + get_length(head->next);
}
ListNode* go(ListNode* l1, ListNode* l2, int& carry){ //使用引用传递
if(!l1){
assert(!l2);
carry = 0;
return NULL;
}
ListNode* next = go(l1->next, l2->next, carry); //递归调用,carry 使用引用传递
int x = l1->val + l2->val + carry; //递归调用过程中使用的都是同一个地方的carry值
ListNode* res = new ListNode(x % 10);
res->next = next;
carry = x / 10;//递归调用过程中修改的都是同一个地方的carry值
return res;
}
};
2. 在python中跟上面C++一样的写法就是错的
错误的代码:
def addTwoNumbers2(l1: ListNode, l2: ListNode) -> ListNode:
def get_len(head):
if not head:
return 0
return 1 + get_len(head.next)
def add(l1,l2,carry):
if not l1:
carry = 0
return None
next = add(l1.next, l2.next,carry) ## !!!!
sum = l1.val + l2.val + carry ## !!!! 无法获取在下一层调用中更新的carry值,这里的这一层函数中的carry值仍然是0
node = ListNode(sum%10)
node.next = next
carry = sum // 10 ## !!!!
return node
len1, len2 = get_len(l1), get_len(l2)
len = max(len1,len2)
head = l1 if len1 < len2 else l2
for i in range(len - min(len1,len2)):
node = ListNode(0)
node.next = head
head = node
if len1 < len2:
l1 = head
else:
l2 = head
carry = 0
res = add(l1,l2,carry)
if carry:
node = ListNode(carry)
node.next = res
res = node
return res
错误的原因:
因为python中每次递归函数调用传递的都是不可变对象(进位值,是一个数值常量),当在函数中 更新carry = x // 10 时,只是该函数内部空间的局部变量(标签)carry又绑定到了另一个不可变对象 x // 10上了,该函数返回到上一级函数中,上一级函数内部空间的局部变量(标签)carry仍然绑定在原来绑定的不可变对象0上,也就是说在python中,这种函数参数传递方式在递归调用中无法获取下一层中的carry更新值
正确的代码:
递归函数返回本层函数调用更新后的carry值
class Solution:
def addTwoNumbers(self, l1, l2):
def add(num1, num2, i, j):
if not i or not j:
return 0
if num1 > num2:
temp = i.val + add(num1 - 1, num2, i.next, j)
else:
temp = i.val + j.val + add(num1, num2, i.next, j.next)
i.val = temp % 10
return temp // 10 # 递归函数返回本层函数调用更新后的carry值
num1 = num2 = 0
cur = l2
while cur:
num2 += 1
cur = cur.next
cur = l1
while cur:
num1 += 1
cur = cur.next
if num2 > num1:
l1, l2 = l2, l1
num2, num1 = num1, num2
if add(num1,num2,l1, l2):
l2 = ListNode(1)
l2.next = l1
l1 = l2
return l1