2. 两数相加

2. 两数相加

 

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

输出:7 -> 0 -> 8

原因:342 + 465 = 807

 

 

 

 

 

 

 

解决方案

方法:初等数学

思路

我们使用变量来跟踪进位,并从包含最低有效位的表头开始模拟逐位相加的过程。

 

 

1,对两数相加方法的可视化: 342 + 465 = 807342+465=807, 每个结点都包含一个数字,并且数字按位逆序存储。

 

算法

 

就像你在纸上计算两个数字的和那样,我们首先从最低有效位也就是列表 l1l1 和 l2l2 的表头开始相加。由于每位数字都应当处于 0 \ldots 90…9 的范围内,我们计算两个数字的和时可能会出现“溢出”。例如,5 + 7 = 125+7=12。在这种情况下,我们会将当前位的数值设置为 22,并将进位 carry = 1carry=1 带入下一次迭代。进位 carrycarry 必定是 00 或 11,这是因为两个数字相加(考虑到进位)可能出现的最大和为 9 + 9 + 1 = 199+9+1=19。

 

 

请特别注意以下情况:

 

测试用例

说明

l1=[0,1]
l2=[0,1,2]

当一个列表比另一个列表长时。

l1=[]
l2=[0,1]

当一个列表为空时,即出现空列表。

l1=[9,9]
l2=[1]

求和运算最后可能出现额外的进位,这一点很容易被遗忘

 

 1 class Solution {
 2 public:
 3     ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
 4         ListNode *p1 = l1, *p2 = l2;
 5         int sum, cf, remain;
 6 
 7         // 个位
 8         sum = p1->val + p2->val;
 9         cf = sum / 10;
10         remain = sum % 10;
11 
12         ListNode *ret = new ListNode(remain);
13         ListNode *p3 = ret;
14 
15         p1 = p1->next;
16         p2 = p2->next;
17 
18         while (p1 != NULL && p2 != NULL)
19         {
20             sum = p1->val + p2->val + cf;
21             cf = sum / 10;
22             remain = sum % 10;
23             
24             p3->next = new ListNode(remain);
25             p3 = p3->next;
26 
27             p1 = p1->next;
28             p2 = p2->next;
29         }
30 
31         while (p1 != NULL)
32         {
33             if (cf != 0)
34             {
35                 sum = p1->val + cf;
36                 cf = sum / 10;
37                 remain = sum % 10;
38 
39                 p3->next = new ListNode(remain);
40                 p3 = p3->next;
41                 p1 = p1->next;
42             }
43             else
44             {
45                 p3->next = new ListNode(p1->val);
46                 p3 = p3->next;
47                 p1 = p1->next;
48             }
49         }
50         while (p2 != NULL)
51         {
52             if (cf != 0)
53             {
54                 sum = p2->val + cf;
55                 cf = sum / 10;
56                 remain = sum % 10;
57 
58                 p3->next = new ListNode(remain);
59                 p3 = p3->next;
60                 p2 = p2->next;
61             }
62             else
63             {
64                 p3->next = new ListNode(p2->val);
65                 p3 = p3->next;
66                 p2 = p2->next;
67             }
68         }
69 
70         if(cf!=0)
71             p3->next = new ListNode(1);
72 
73         return ret;
74     }
75 };

 


复杂度分析:

时间复杂度:O(\max(m, n))O(max(m,n)),假设 mm 和 nn 分别表示 l1l1 和 l2l2 的长度,上面的算法最多重复 \max(m, n)max(m,n) 次。

空间复杂度:O(\max(m, n))O(max(m,n)), 新列表的长度最多为 \max(m,n) + 1max(m,n)+1。

 

 

posted @ 2018-10-21 11:15  阿卡阿卡啊卡卡卡  阅读(209)  评论(0编辑  收藏  举报