python 算法 - 008 计算两个链表所代表的整数之和 (整数相加法)
知之者不如好之者, 好之者不如乐之者.--《雍也》
知道德者不如好道德者, 好道德者不如乐道德者, 是为形容人道德之深.
电脑修好了.
题目: 给定两个链表, 链表的每一个节点代表一位数, 个位数在链表的前面, 要求两个链表所代表的整数的和, 并用一个链表表示出来. 例如: head1->1->3->4->5 和 head2->2->1->6->2, 所代表的数分别为: 54311,26122,=>54311+26122=80433, 用链表表示为 Head->3->3->4->0->8.
今天的题目说简单, 却有点复杂, 说复杂却很好理解 (废话). 往简单的说: 分别求出两个链表代表的整数, 相加, 将结果存入链表输出即可. 你肯定会想: 这太简单了, 操作起来没有任何难度. 不管如何, 我们先来看一下这 "简单" 到底简不简单.
求链表的和: 因为每个节点保存的是一位数, 每向后遍历一个节点, 都要乘 10^n, 并累加到 sum. 但是 n 越来越大, sum 也越来越大. 最终会超过长整型的最大范围, 那怎么办呢, 后面我会详细讲, 现在先来看看, 怎么实现这 "简单的方法": 这里我用的 reduce 函数, 这个函数在 python3 里是被封装到了 functools 里. 可能有同学不太了解这个函数 (我自己也不太熟, 这里是一次小练习, 混个脸熟)-- 这里有个直通车 map/reduce 可以让大家理解这个函数. 这个函数用来求累加和非常容易. 也可以不用这个, 可以用一个 i 来保存当前是第几位, 然后边遍历, 边求和, 同样能求出来.fromfunctoolsimportreduce
# 用于求和
deffn(x,y):
returnx*10+y
# 求链表所代表的数
defsumlink(head):
Sum=0# 保存和
cur=head.next
List=[]#用于保存链表的每一个节点
whilecurisnotNone:
#将节点保存在第一位
List.insert(0,cur.data)
cur=cur.next
ifheadisnotNoneorhead.nextisnotNone:
Sum=reduce(fn,List)
print("head's Sum :",Sum)
returnSum
这里现在我不太熟, 以后我找时间学学.
下面的是将和存入链表的函数: 将和从整型转换为字符串, 让其可迭代. 然后依次存入, 然后逆序链表, 这被我之前写复杂了, 逆序用的是第一次写的就地逆序法, 因为当时对递归法, 插入法还不熟悉, 所以代码不够精简. 其实完全可以先把字符串逆序, 然后放进去, 但是字符串逆序又要一步操作, 实在是太繁琐了, 违背了 python 精简的初衷, 当初也是没多想, 就当时复习一下了. 但是在面试时遇到这样的问题时, 一定不要用这个方法. 因为费时费力, 还容易出错, 光是前面的求链表对应的整数都是一个问题. 不过这里还是给出代码:deffunction(head1,head2):
Sum=sumlink(head1)+sumlink(head2)
print("sum is",Sum)
Sum=str(Sum)
head=LNode(None)
cur=head
tmp=None
foriinSum:
tmp=LNode(i)
cur.next=tmp
cur=cur.next
#开始逆序链表 -- 就地逆序法
# 判断链表是否为空
ifheadisNoneorhead.nextisNone:
return
# 处理链表头
cur=head.next
next=cur.next
cur.next=None
pre=cur
cur=next
# 转变当前节点指向
whilecur.next!=None:
next=cur.next
cur.next=pre
pre=cur
cur=next
# 处理最后一个节点与倒数第二个节点
cur.next=pre
# 添加头节点
head.next=cur
returnhead
主程序:if__name__=='__main__':
head1=creatLink(10)
head2=creatLink(10)
print("head1:")
cur=head1.next
whilecur!=None:
print(cur.data)
cur=cur.next
print("head2:")
cur=head2.next
whilecur!=None:
print(cur.data)
cur=cur.next
head=function(head1,head2)
print("\nAfteplus:")
cur=head.next
whilecur!=None:
print(cur.data)
cur=cur.next
输出结果:
输出结果
虽然过程曲折, 但是我们还是完成了这个题目的要求. 但是这种方法的缺点非常明显, 一旦链表保存的整数超过了长整型的最大数值, 程序就会报错. 明天我会介绍链表直接相加的方法, 这种方法就像是一种加法器, 是一位一位加的, 更符合我们平时的计算方法. 而且理论上, 只要你电脑内存够, 就可以一直算下去. 这比上面的方法好多了.
全部的代码如下:importrandom
fromfunctoolsimportreduce
classLNode:
"""docstring for LNode"""
def__init__(self,arg):
self.data=arg
self.next=None
"""
题目描述:
将 Head->1->1->3->3->5->7->7->8
与 head->1->2->5->7->8 相加
得 Head->2->3->8->0->4->8->7->8
个位在前
方法: 整数相加, 先求 h1 的和, 再求 h2 的和, 然后相加, 最后根据和新建链表
"""
# 构造链表
defcreatLink(x):
i=1
head=LNode(None)
tmp=None
cur=head
whilei<=x:
n=random.randint(1,9)
tmp=LNode(n)
cur.next=tmp
cur=tmp
i+=1
returnhead
# 用于求和
deffn(x,y):
returnx*10+y
# 求链表所代表的数
defsumlink(head):
Sum=0# 保存和
cur=head.next
List=[]#用于保存链表的每一个节点
whilecurisnotNone:
#将节点保存在第一位
List.insert(0,cur.data)
cur=cur.next
ifheadisnotNoneorhead.nextisnotNone:
Sum=reduce(fn,List)
print("head's Sum :",Sum)
returnSum
deffunction(head1,head2):
Sum=sumlink(head1)+sumlink(head2)
print("sum is",Sum)
Sum=str(Sum)
head=LNode(None)
cur=head
tmp=None
foriinSum:
tmp=LNode(i)
cur.next=tmp
cur=cur.next
# 判断链表是否为空
ifheadisNoneorhead.nextisNone:
return
# 处理链表头
cur=head.next
next=cur.next
cur.next=None
pre=cur
cur=next
# 转变当前节点指向
whilecur.next!=None:
next=cur.next
cur.next=pre
pre=cur
cur=next
# 处理最后一个节点与倒数第二个节点
cur.next=pre
# 添加头节点
head.next=cur
returnhead
if__name__=='__main__':
head1=creatLink(10)
head2=creatLink(10)
print("head1:")
cur=head1.next
whilecur!=None:
print(cur.data)
cur=cur.next
print("head2:")
cur=head2.next
whilecur!=None:
print(cur.data)
cur=cur.next
head=function(head1,head2)
print("\nAfteplus:")
cur=head.next
whilecur!=None:
print(cur.data)
cur=cur.next
今天的就先讲到这里了, 今天的算法其实也没多大用, 所以注释就没写这么详细, 但是电脑刚修好, 很多东西还在弄. 昨天提到的流程图还要一段时间, 最近学校课程安排也是很紧, 明天晚上要上课, 可能明天的算法会晚一点. 等周五我才空下来, 我会好好整理下. 争取在周末给大家分享一个小爬虫案例. 爬哪个网站还没想好, 就先这样子.
还是那句话, 我只是需要被需要 -- 再我的 https://github.com/Gesujian/python- 有所有的代码, 当然可能会有所出入, 但相差不多, 欢迎大家学习!
这是我微信公众号: Dkider 方便大家联系我.
DKider
君子之于天下也, 无适也, 无莫也, 义之与比.--《论语》
来源: http://www.jianshu.com/p/facc0169d773