题目描述
给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。(如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转)
输入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出: 7 -> 8 -> 0 -> 7
解题思路
本题有“后进先出”的特点,考虑用“栈”来解决,主要有两种思路:
- 双栈解法(推荐,我的实现):遍历两个链表,将指向节点的指针存入两个栈中。从栈顶开始取节点的值求和。每求出一对节点的和,出栈节点。直到两栈都为空。
- 递归解法(看看思路就好):先计算两个链表的长度,然后对短链表前面补
0
使两个链表长度相同,使用递归先计算最末尾节点,利用递归的回溯特性,不断更新carry
进位与新的结果头节点。
参考代码
双栈法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
vector<ListNode*> l1v, l2v;
to_vector(l1, l1v);
to_vector(l2, l2v);
int i = l1v.size()-1, j = l2v.size()-1;
int tempNum = 0;
ListNode *dummyHead = new ListNode(-1);
dummyHead->next = nullptr;
while(i >= 0 || j >= 0){
if(i >= 0) tempNum += l1v[i--]->val;
if(j >= 0) tempNum += l2v[j--]->val;
ListNode* tempNode = new ListNode(tempNum % 10); // 头插法
tempNode->next = dummyHead->next;
dummyHead->next = tempNode;
tempNum /= 10;
}
if(tempNum != 0) { // 最后最高位是否有进位
ListNode* tempNode = new ListNode(tempNum);
tempNode->next = dummyHead->next;
dummyHead->next = tempNode;
}
return dummyHead->next;
}
void to_vector(ListNode* head,vector<ListNode*>& v){
while(head){
v.push_back(head);
head = head->next;
}
}
};
递归法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
int length(ListNode *head) {
if (head == nullptr) return 0;
return 1 + length(head->next);
}
int addTwoNumbersHelper(ListNode *l1, ListNode *l2, ListNode *&res) { // 必须用 *&
if (l1 == nullptr || l2 == nullptr) return 0;
int carry = addTwoNumbersHelper(l1->next, l2->next, res);
int sum = l1->val + l2->val + carry;
auto newHead = new ListNode(sum % 10);
newHead->next = res;
res = newHead;
return sum / 10;
}
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
int m = length(l1), n = length(l2);
ListNode *res = nullptr;
// 让两个链表长度相同
int carry = 0;
if (m > n) {
int k = m - n;
ListNode *dummy = new ListNode(0);
dummy->next = l2;
while (k--) {
ListNode *t = new ListNode(0);
t->next = dummy->next;
dummy->next = t;
}
carry = addTwoNumbersHelper(l1, dummy->next, res);
} else if (m < n) {
int k = n - m;
ListNode *dummy = new ListNode(0);
dummy->next = l1;
while (k--) {
ListNode *t = new ListNode(0);
t->next = dummy->next;
dummy->next = t;
}
carry = addTwoNumbersHelper(dummy->next, l2, res);
} else {
carry = addTwoNumbersHelper(l1, l2, res);
}
if (carry) {
ListNode *newHead = new ListNode(1);
newHead->next = res;
res = newHead;
}
return res;
}
};