博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode:Add Two Numbers
阅读量:7250 次
发布时间:2019-06-29

本文共 3543 字,大约阅读时间需要 11 分钟。

You are given two linked lists representing two non-negative numbers. 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.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) 

Output: 7 -> 0 –> 8

大整数加法


注意:链表中,整数的低位在前                       

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 
* 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) {
        
int 
carryBit = 0;
        
ListNode tmpHead(0), *res = &tmpHead;
        
while
(l1 && l2)
        
{
            
l1->val += (l2->val + carryBit);
            
carryBit = l1->val / 10;
            
l1->val %= 10;
            
res->next = l1;
            
res = l1;
             
            
l1 = l1->next;
            
l2 = l2->next;
        
}
        
ListNode *p = (l1 == NULL ? l2 : l1);
//此时l1,l2至多一个不为NULL
        
while
(p)
        
{
            
if
(carryBit == 0)
            
{
                
res->next = p;
                
break
;
            
}
            
else
            
{
                
p->val += carryBit;
                
carryBit = p->val / 10;
                
p->val %= 10;
                
res->next = p;
                
res = p;
            
}
            
p = p->next;
        
}
        
if
(carryBit != 0)res->next =
new 
ListNode(carryBit);
         
        
return 
tmpHead.next;
    
}
};


如果链表存储整数时,高位在前,该如何处理。

1、最简单的想法是,可以先把链表反转,然后调用上面的算法,最后把结果反转。

2、可不可以从高位向低位方向处理呢?我们知道进位是从低位传向高位的,如果从高位向低位方向计算,当计算到某一位需要进位时,有没有办法知道该进位传递到前面的哪一位呢?从以下几个例子来看:

从最高位到最低位我们依次记为第 1,2…,7位。图中红色标记的位置是:下一次需要进位时,进位的1放置的位子

第1位相加,结果为12,需要进位,这个进位放到第0位;同时标记第1位为下一次的进位标志

第2位相加,结果为3,不需要进位;标记第2位为下一次进位标志

第3位相加,结果为3,不需要进位;标记第3位为下一次进位标志

第4位相加,结果为9,不需要进位;此时进位标志不需要移动,因为9加上一个进位后还要继续向前进位

第5位相加,结果为9,不需要进位;此时进位标志不需要移动,因为9加上一个进位后还要继续向前进位

第6位相加,结果为14,需要进位,这个进位放到前面标记的第3位上,同时把第4位和第5位置0,标记第6位为下一次进位标志

第7位同上

 

所以综上所述,从高位往低位计算加法时,规则是:

一、如果当前位没有进位:(1)如果当前位的和小于9,则把改位设置成下一次进位标志(2)如果和等于9,进位标志不变

二、如果当前位有进位:把进位的1加到前面标志的位子上,同时把标志位和当前位之间的位全部置0(因为他们之间的位肯定全部都是9),把当前位设置成进位标志

 

上面我们举例的两个加数长度一致,如果长度不相同,则要先处理较长的整数的前面多出的部分。

 

我们把这一题leetcode的输入反转,测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
 
* 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) {
        
l1 = reverseList(l1);
        
l2 = reverseList(l2);
        
int 
n1 = lenList(l1), n2 = lenList(l2);
        
if
(n1 < n2)
//l1 指向较长的链表
        
{
            
swap(n1,n2);
            
swap(l1,l2);
        
}
        
//carryLoc是下一次出现进位时,进位的1将要放置的位子,pre指向当前结果链表的最后一个节点
        
//p1,p2分别是当前处理的l1,l2节点
        
//由于加数的最高位有可能进位,所以添加一个新的节点newHead
        
ListNode *newHead =
new 
ListNode(0), *carryLoc = newHead, *pre = newHead, *p1 = l1;
        
for
(
int 
i = 0; i < n1-n2; i++)
//处理l1高位长出的部分
        
{
            
if
(p1->val < 9)carryLoc = p1;
            
pre->next = p1;
            
pre = p1;
            
p1 = p1->next;
        
}
        
ListNode* p2 = l2;
        
while
(p1 != NULL)
        
{
            
pre->next = p1;
            
pre = p1;
             
            
p1->val += p2->val;
            
if
(p1->val > 9)
            
{
                
carryLoc->val += 1;
                
for
(carryLoc = carryLoc->next; carryLoc != p1; carryLoc = carryLoc->next)
//carryLoc到p1之间的节点全部置0
                    
carryLoc->val = 0;
                
p1->val -= 10;
            
}
            
if
(p1->val < 9)
                
carryLoc = p1;
             
            
p1 = p1->next;
            
p2 = p2->next;
        
}
        
if
(newHead->val != 0)
return 
reverseList(newHead);
        
else 
return 
reverseList(newHead->next);
    
}
    
//反转链表
    
ListNode *reverseList(ListNode *l1)
    
{
        
ListNode *p = l1->next, *pre = l1;
        
l1->next = NULL;
        
while
(p)
        
{
            
ListNode *tmp = p->next;
            
p->next = pre;
            
pre = p;
            
p = tmp;
        
}
        
return 
pre;
    
}
    
//求链表长度
    
int 
lenList(ListNode *head)
    
{
        
int 
res = 0;
        
while
(head)
        
{
            
res++;
            
head = head->next;
        
}
        
return 
res;
    
}
};

 

本文转自tenos博客园博客,原文链接:http://www.cnblogs.com/TenosDoIt/p/3735362.html,如需转载请自行联系原作者
你可能感兴趣的文章
Git for Windows 2.21.0 发布,Win 下的 Git 客户端
查看>>
JSON和XML格式转换
查看>>
XXL-RPC v1.3.2,分布式服务框架
查看>>
将c++静态库实现二次封装供java调用
查看>>
在阿里云kubernetes上部署Jenkins Master
查看>>
VueJs开发笔记—IDE选择和优化、框架特性、数据调用、路由选项及使用
查看>>
MySQL 数据库的备份与恢复
查看>>
Android中的设计模式之单例模式
查看>>
使用Cordova将您的前端JavaScript应用打包成手机原生应用
查看>>
用Python玩转微信
查看>>
Bootstrap 小结
查看>>
《JavaScript权威指南》——JavaScript核心
查看>>
C语言 时间函数的学习
查看>>
你真的懂Redis事务吗?
查看>>
收藏 | 12个ggplot2拓展程序助你强化R可视化
查看>>
1-Linux C语言编程基本原理与实践-学习笔记
查看>>
WRF-DA代码编译与安装(二)——WRF-DA模块的编译与安装
查看>>
2018年美团Android校招
查看>>
Spring消息之WebSocket
查看>>
Java 文件流操作.
查看>>