题目链接:https://leetcode.com/problems/add-two-numbers/
题目难度:Medium
题目描述:
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example:
Input:
(2 -> 4 -> 3) + (5 -> 6 -> 4)
Output:7 -> 0 -> 8
Explanation: 342 + 465 = 807.
相关主题:Linked List, Math
链表定义:
// C++
struct ListNoe {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
思路 1
头结点对应的是个位数,可以从头结点开始,同步遍历两个链表,算出每一步的结果和进位,同时创建新的链表存放结果。关键还是对链表、指针的操作。
时间复杂度:
空间复杂度:
// C++
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
ListNode *result = new ListNode(0);
ListNode *pl1 = l1, *pl2 = l2, *pr = result;
int sum = 0, carry = 0;
while (pl1 != NULL or pl2 != NULL) {
sum = 0;
if (pl1 != NULL) {
sum += pl1->val;
pl1 = pl1->next;
}
if (pl2 != NULL) {
sum += pl2->val;
pl2 = pl2->next;
}
sum += carry;
pr->val = sum % 10;
carry = sum / 10;
if (pl1 == NULL && pl2 == NULL) {
if (carry > 0) {
pr->next = new ListNode(carry);
}
} else {
pr->next = new ListNode(0);
pr = pr->next;
}
}
return result;
}
};
思路 2
题目没有对返回的链表作额外的要求,看到也有人将两个链表的和加到其中一个链表上,并返回这个链表。这样程序的开销会小一些,但是从最差的情况考虑,时间复杂度和空间复杂度应该还都是 。
时间复杂度:
空间复杂度:
// C++
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
ListNode *pl1 = l1, *pl2 = l2;
int sum = 0, carry = 0;
while (pl2->next != NULL) {
sum = pl1->val + pl2->val + carry;
carry = sum / 10;
pl1->val = sum % 10;
if (pl1->next == NULL) {
pl1->next = new ListNode(0);
}
pl1 = pl1->next;
pl2 = pl2->next;
}
sum = pl1->val + pl2->val + carry;
carry = sum / 10;
pl1->val = sum % 10;
while (carry > 0) {
if (pl1->next == NULL) {
pl1->next = new ListNode(carry);
break;
} else {
pl1 = pl1->next;
sum = pl1->val + carry;
carry = sum / 10;
pl1->val = sum % 10;
}
}
return l1;
}
};
关于本地调试
为了在本地调试方便,添加了从 vector
创建链表、打印链表、销毁链表的代码:
// C++
ListNode *create_list(vector<int> v)
{
if (v.size() > 0) {
ListNode *head = new ListNode(v[0]);
ListNode *p = head;
for (int i = 1; i < v.size(); i++) {
p->next = new ListNode(v[i]);
p = p->next;
}
return head;
} else {
return NULL;
}
}
void print_list(ListNode *head)
{
ListNode *p = head;
while (p != NULL) {
cout << p->val;
if (p->next == NULL) {
cout << endl;
} else {
cout << " -> ";
}
p = p->next;
}
}
void destruct_list(ListNode *head)
{
ListNode *p = head;
while (head != NULL) {
head = head->next;
delete p;
p = head;
}
}
为了方便初始化,这里先把链表中的元素放到了 vector
里。测试代码:
void test(Solution s, vector<int> v1, vector<int> v2)
{
ListNode *l1 = create_list(v1), *l2 = create_list(v2);
cout << "Input:" << endl;
print_list(l1);
print_list(l2);
ListNode *result = s.addTwoNumbers(l1, l2);
cout << "Output:" << endl;
print_list(result);
if (l1 == result) {
destruct_list(l1);
} else {
destruct_list(l1);
destruct_list(result);
}
destruct_list(l2);
}
int main(int argc, char *argv[])
{
vector<int> v1 = {2, 4, 3}, v2 = {5, 6, 4}, v3 = {9, 8}, v4 = {1}, v5 = {9};
Solution s;
test(s, v1, v2);
test(s, v1, v3);
test(s, v3, v4);
test(s, v3, v1);
test(s, v4, v5);
return 0;
}
因为涉及到对指针的操作,稍有不慎就会造成内存泄漏。所以在本地调试时可以使用 Valgrind 进行内存泄漏检测。例如:
$ g++ demo.cpp -o demo -std=c++11
$ valgrind ./demo
==32266== Memcheck, a memory error detector
==32266== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==32266== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==32266== Command: ./demo
==32266==
Input:
2 -> 4 -> 3
5 -> 6 -> 4
Output:
7 -> 0 -> 8
Input:
2 -> 4 -> 3
9 -> 8
Output:
1 -> 3 -> 4
Input:
9 -> 8
1
Output:
0 -> 9
Input:
9 -> 8
2 -> 4 -> 3
Output:
1 -> 3 -> 4
Input:
1
9
Output:
0 -> 1
==32266==
==32266== HEAP SUMMARY:
==32266== in use at exit: 72,704 bytes in 1 blocks
==32266== total heap usage: 49 allocs, 48 frees, 73,280 bytes allocated
==32266==
==32266== LEAK SUMMARY:
==32266== definitely lost: 0 bytes in 0 blocks
==32266== indirectly lost: 0 bytes in 0 blocks
==32266== possibly lost: 0 bytes in 0 blocks
==32266== still reachable: 72,704 bytes in 1 blocks
==32266== suppressed: 0 bytes in 0 blocks
==32266== Rerun with --leak-check=full to see details of leaked memory
==32266==
==32266== For counts of detected and suppressed errors, rerun with: -v
==32266== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
上面终端输出的 LEAK SUMMARY
就反映了内存的泄漏情况。
2019年03月29日