题目
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
进阶:
如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
示例:
输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 8 -> 0 -> 7
解析
该题目有一个困惑点,就是结果要不要重用输入链表,重用的话有一个结果链表处理进位的问题,不重用的话直接创建节点会减少很多工作量,缺点就是空间占用会较多。
最容易想的方法就是翻转加完再翻转。不允许翻转的话,就是借助空间了,可以用一个辅助数组,长度的较长链表的长度,在链表上处理进位,再输出结果。第三种就是借助题目设定的反向处理——压栈,先入后出。
解法1:利于数组,重用输入链表,时间空间都很有效
class Solution {
int cntNodes(ListNode* list) {
if (NULL == list)
return 0;
int len = 0;
while (list) {
++len;
list = list->next;
}
return len;
}
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if (NULL == l1)
return l2;
if (NULL == l2)
return l1;
//l1指向长链表
int len1 = cntNodes(l1);
int len2 = cntNodes(l2);
if (len1 < len2) {
swap(l1, l2);
swap(len1, len2);
}
//tmp存两个数的和
vector<int> tmp(len1);
ListNode *p = l1;
for (int i = 0; i < len1; ++i) {
tmp[i] = p->val;
p = p->next;
}
p = l2;
for (int i = len1-len2; i < len1; ++i) {
tmp[i] += p->val;
p = p->next;
}
//处理进位
int chg = 0;
for (int i = len1-1; i >= 0; --i) {
tmp[i] = tmp[i]+chg;
chg = tmp[i]/10;
tmp[i] = tmp[i]%10;
}
//将数存入长链表
p = l1;
for (int i = 0; i < len1; ++i) {
p->val = tmp[i];
p = p->next;
}
if (chg) {
ListNode* node = new ListNode(chg);
node->next = l1;
return node;
}
return l1;
}
};
空间是O(max(m,n)),时间O(m+n)
解法2:利用栈,不重用输入链表
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if (NULL == l1)
return l2;
if (NULL == l2)
return l1;
//链表入栈
stack<int> sta1;
stack<int> sta2;
ListNode *p = l1;
while (p) {
sta1.push(p->val);
p = p->next;
}
p = l2;
while (p) {
sta2.push(p->val);
p = p->next;
}
//节点出栈
ListNode dummy(0);
ListNode *node = &dummy;
int chg = 0;
while (!sta1.empty() || !sta2.empty()) {
int num = 0;
if (!sta1.empty()) {
num = sta1.top();
sta1.pop();
}
if (!sta2.empty()) {
num += sta2.top();
sta2.pop();
}
num += chg;
chg = num/10;
num %= 10;
p = new ListNode(num);
p->next = node->next;
node->next = p;
}
if (chg) {
p = new ListNode(chg);
p->next = node->next;
node->next = p;
}
return dummy.next;
}
};
题解说用栈时间复杂度是O(max(m,n))(为啥我觉得是O(m+n)呢,压栈也算是遍历啊,不是压了两个栈么。。。),空间是O(m+n)。重用输入链表会带来很多的工作量。具体看自己怎么实现。