【被OJ毒打的第八天】LeetCode_中等_2.两数相加
题干:
给出两个非空的链表用来表示两个非负的整数,我们将这两个数相加,返回一个新的链表来表示它们的和
提示:
它们各自的位数是按照逆序的方式存储的
每个节点只能存储一位数字
除了数字 0 之外,这两个数的尾结点都不会是 0
输入:
(2->4->3) + (5->6->4)
输出:
7->0->8 // 342 + 465 = 807
1.我的做法
执行用时:32~40ms,10.4MB
思想:用一个额外的变量记录进位;遍历链表,将对应位置的数以及进位相加计算出一个临时值,接着判断这个临时值有没有超过 10,如果超过需要进位
实现:傻瓜式实现,有大量冗余代码
踩坑:注意用例 [5] + [5] = [0,1],即当两个链表都为空但有进位时的处理!
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if (l1 == NULL) {
return l2;
}
if (l2 == NULL) {
return l1;
}
ListNode* res = new ListNode(-1);
ListNode* p = res;
int up = 0; // 存储进位
while (l1 != NULL && l2 != NULL) {
int tmp = l1->val + l2->val + up;
if (tmp >= 10) {
up = 1;
p->next = new ListNode(tmp - 10);
} else {
up = 0;
p->next = new ListNode(tmp);
}
p = p->next;
l1 = l1->next;
l2 = l2->next;
}
while (l1 != NULL) {
int tmp = l1->val + up;
if (tmp >= 10) {
up = 1;
p->next = new ListNode(tmp - 10);
} else {
up = 0;
p->next = new ListNode(tmp);
}
p = p->next;
l1 = l1->next;
}
while (l2 != NULL) {
int tmp = l2->val + up;
if (tmp >= 10) {
up = 1;
p->next = new ListNode(tmp - 10);
} else {
up = 0;
p->next = new ListNode(tmp);
}
p = p->next;
l2 = l2->next;
}
if (up == 1) {
p->next = new ListNode(1);
}
return res->next;
}
2.进阶做法
执行用时:24~36ms,10.3MB
思想:大致同上,但是实现做了精简和优化
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(-1);
int carry = 0;
int x, y;
int sum;
ListNode* curr = head;
while (l1 != NULL || l2 != NULL) {
x = (l1 ? l1->val : 0);
y = (l2 ? l2->val : 0);
sum = x + y + carry;
carry = sum / 10;
curr->next = new ListNode(sum % 10);
if (l1)
l1 = l1->next;
if (l2)
l2 = l2->next;
curr = curr->next;
}
if (carry == 1) {
curr->next = new ListNode(1);
}
return head->next;
}
其他 12~24ms 的样例代码执行出来之后时间也在 24~36ms 左右...而且思路实现几乎没有什么不同......
3.另类解法
执行用时:32ms,10.5MB(在 Java 解法中能排到前 7%,可惜在 C++ 中似乎没有这么好的表现)
思想:递归,将前一位运算结果也传入函数,以此来判断是否进位
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
return addTwoNumbers(l1, l2, NULL);
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2, ListNode* prev) {
int val1 = 0;
int val2 = 0;
if (l1 != NULL) {
val1 = l1->val;
l1 = l1->next;
}
if (l2 != NULL) {
val2 = l2->val;
l2 = l2->next;
}
ListNode* n = new ListNode(val1 + val2);
if (prev != NULL) {
if (prev->val >= 10) {
prev->val -= 10;
n->val += 1;
}
}
if (l1 != NULL || l2 != NULL) {
n->next = addTwoNumbers(l1, l2, n);
} else if (n->val >= 10) {
n->next = addTwoNumbers(l1, l2, n);
}
return n;
}
};
中等题目相比简单题目果然还是有点东西的~目前感觉主要表现在需要考虑的边缘情况更多了,必要的步骤也更多了,所以代码整体的执行时间都会有所增加~
今晚花旗杯开会了→_→所以很可能明后天要鸽一鸽...