python输入两个整数求和_python算法--009计算两个链表所代表的整数之和(链表相加法)...

两人对酌山花开,一杯一杯复一杯。——李白《山中与幽人对酌》

李白喝了酒,写的诗这么棒;如果我喝了写代码,那电脑可能会崩溃。

题目:题目:给定两个链表,链表的每一个节点代表一位数,个位数在链表的前面,要求两个链表所代表的整数的和,用一个链表表示出来。例如:head1->1->3->4->5 和 head2->2->1->6->2,所代表的数分别为:54311,26122,=>54311+26122=80433,用链表表示为Head->3->3->4->0->8。

昨天讲的整数相加法好像没几个人看,今天介绍的是链表相加法,那么如何链表相加呢?下面跟我一起来看一下:

一样先来分析一下问题,要求的是链表代表的整数的和,那么不用链表代表的整数和怎么算呢?我给出了几个小栗子:

1 + 1 = 2

111 + 111 = 222

2 + 9 = 11

112 + 19 = 131

11 + 999 = 1010

999,987,654,321 + 9,876,543 = 999,997,530,864

这几个栗子可以代表绝大多数情况(这里不考虑负数):第一个和第二个,都代表的是长度相等的情况,而且都没有进位;第三个,长度相等,但是有进位;第四个长度不等,有进位,但是最高位没有进位;第五个,长度不等,有进位,且最高位有进位;第六个,这是最长的一个,也是最为常见的情况,我用逗号将他们分开了好让大家看到位数,可以看到这是一个12位数加7位数,我们自己在用笔算的时候是这样一个过程(字丑。。。很久没写字了,更丑了):

MJZfQr.jpg 计算过程

我们是以个位对齐,并从个位开始相加,每一位都加。如果大于10,则向前进1。这大家小学都学过。但是到了短的数算完了,也就是遍历到上面的8,这一位是只加了一个进位1,最高的四位,9999是直接加到了和的前面。 当然更规范来说,每一位都加了进位,高位的9999也是都加了进位,但是此时进位为0。对于整数的算法就这样,那我们下面来看,如果是保存在链表里的数怎么办?

我们的链表是将个位保存在了第一位,这与我们的笔算顺序是一致的。用程序语言来说:从链表头开始,每一位相加,并记录是否有进位。将结果的个位存入新的链表对应的位置,然后遍历下一个节点,一样是相加,同时还要加上进位C。过程中如果短的链表加完了,那么短的链表停止遍历,继续遍历长的链表,记得加上进位。当所有的都遍历完了,也要考虑进位,因为,当两个链表长度相同时,加完了是否还有进位。具体详细的我在代码的注释里都写上了,大家仔细看下,注意点还是蛮多的。

我怕代码太长你们不愿意看,我就先放求和函数的代码,这看起来很长,其实只是我注释写的比较多:

#输入两个链表,计算链表代表整数的和,并将其存入链表返回

def function(head1,head2):

#判断两个链表是否都为空为空,为空则返回空链表

if head1.next is None and head2.next is None:

return head1

cur1=head1.next # 指向head1的第一个节点

cur2=head2.next # 指向head2的第一个节点

c=0#用来记录进位

newhead=LNode(None)#这是相加之后产生的新链表,这里称为和

cur=newhead#指向和

#当两个链表至少有一个还没有遍历完时,循环

#这里比较复杂,有三种情况

#(1)当head1遍历完了

#(2)当head2遍历完了

#(3)两个都没有遍历完

while cur1 is not None or cur2 is not None:

#head1遍历完了

if cur1 is None:

#此时head2是有数据的,head1没有,这里注意加上进位

sumL = cur2.data + c

#head2遍历完了

elif cur2 is None:

#此时head1是有数据的,head2没有,这里注意加上进位

sumL = cur1.data + c

# 都没遍历完

else:

#这时两个都有数据,加上进位

sumL = cur1.data + cur2.data + c

#判断是否产生进位

if sumL>=10:

c=1

else:

c=0

#将该位的和的个位存储为一个节点,并接在总和链表的后面

n=sumL%10

tmp=LNode(n)

cur.next=tmp

cur=tmp

#这里是用于循环的语句,这里是需要判断一下的,

#因为,如果有一个链表先遍历完了,也就是短的那条

#此时cur是None,如果运行cur1=cur1.next,会报错

#提示cur为空类型,没有next属性

#所以这里要先判断,如果为空,就不做变化

#前面的循环判断语句while cur1 is not None or cur2 is not None:

#这里我用的 OR 所以要两个都为空才能出循环,这样就省去了判断谁长谁短的步骤了

if cur1 is not None:

cur1=cur1.next

if cur2 is not None:

cur2=cur2.next

# 注意!!!!假如两个链表一样长,最后的一位相加大于10,

# 程序是直接存储了个位,就直接退出了,并没有考虑c进位

# 所以这里单拿出来判断下

if c==1:

tmp=LNode(1)

cur.next = tmp

cur = tmp

#结束后直接返回存储着两个链表的和的链表

return newhead

前面的构造链表我写了很多次,这里就先不放,我放到最后的总代码里,下面我们来验证一下,是否可行,我试了各种情况:

if __name__ == '__main__':

#构造链表,这里可以多试几次,用不同的长度

head1 = creatLink(8)

head2 = creatLink(1)

#打印head1head2

print("head1:")

cur = head1.next

while cur != None:

print(cur.data)

cur = cur.next

print("head2:")

cur = head2.next

while cur != None:

print(cur.data)

cur = cur.next

#调用求和函数

head = function(head1, head2)

#打印和链表

print("\nAfteplus:")

cur = head.next

while cur != None:

print(cur.data)

cur = cur.next

一位加一位:

Uviuqy.png 1+1

空链表加空链表这很重要,很多人的程序都没考虑到这个,都会报错:

emAb2e.png 0+0

两个长度相同的:

6ZnQ3e.png 8+8

长度不同的:

e2i2Af.png 8+1

我自己还试过1000000位+1000000位的,时间长了一点,但是没报错,结果也对,理论上,可以算。。。很长的数值相加

–,结果太长,我就不贴图了,大家自己试一试。

这是全部的代码,构造链表的代码啥的都在里面:

import random

#定义链表节点类型

class LNode:

"""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

个位在前

方法:链表相加

"""

#构造链表

def creatLink(x):

i = 1

head = LNode(None)

tmp = None

cur = head

while i <= x:

n = random.randint(0, 9)

tmp = LNode(n)

cur.next = tmp

cur = tmp

i += 1

return head

#输入两个链表,计算链表代表整数的和,并将其存入链表返回

def function(head1,head2):

#判断两个链表是否都为空为空,为空则返回空链表

if head1.next is None and head2.next is None:

return head1

cur1=head1.next # 指向head1的第一个节点

cur2=head2.next # 指向head2的第一个节点

c=0#用来记录进位

newhead=LNode(None)#这是相加之后产生的新链表,这里称为和

cur=newhead#指向和

#当两个链表至少有一个还没有遍历完时,循环

#这里比较复杂,有三种情况

#(1)当head1遍历完了

#(2)当head2遍历完了

#(3)两个都没有遍历完

while cur1 is not None or cur2 is not None:

#head1遍历完了

if cur1 is None:

#此时head2是有数据的,head1没有,这里注意加上进位

sumL = cur2.data + c

#head2遍历完了

elif cur2 is None:

#此时head1是有数据的,head2没有,这里注意加上进位

sumL = cur1.data + c

# 都没遍历完

else:

#这时两个都有数据,加上进位

sumL = cur1.data + cur2.data + c

#判断是否产生进位

if sumL>=10:

c=1

else:

c=0

#将该位的和的个位存储为一个节点,并接在总和链表的后面

n=sumL%10

tmp=LNode(n)

cur.next=tmp

cur=tmp

#这里是用于循环的语句,这里是需要判断一下的,

#因为,如果有一个链表先遍历完了,也就是短的那条

#此时cur是None,如果运行cur1=cur1.next,会报错

#提示cur为空类型,没有next属性

#所以这里要先判断,如果为空,就不做变化

#前面的循环判断语句while cur1 is not None or cur2 is not None:

#这里我用的 OR 所以要两个都为空才能出循环,这样就省去了判断谁长谁短的步骤了

if cur1 is not None:

cur1=cur1.next

if cur2 is not None:

cur2=cur2.next

# 注意!!!!假如两个链表一样长,最后的一位相加大于10,

# 程序是直接存储了个位,就直接退出了,并没有考虑c进位

# 所以这里单拿出来判断下

if c==1:

tmp=LNode(1)

cur.next = tmp

cur = tmp

#结束后直接返回存储着两个链表的和的链表

return newhead

if __name__ == '__main__':

#构造链表,这里可以多试几次,用不同的长度

head1 = creatLink(1000000)

head2 = creatLink(1000000)

#打印head1head2

print("head1:")

cur = head1.next

while cur != None:

print(cur.data)

cur = cur.next

print("head2:")

cur = head2.next

while cur != None:

print(cur.data)

cur = cur.next

#调用求和函数

head = function(head1, head2)

#打印和链表

print("\nAfteplus:")

cur = head.next

while cur != None:

print(cur.data)

cur = cur.next

总结一下,这个算法还是很重要的,因为它可以算很大的数,比昨天的整数相加法要好很多。改一下代码,就能计算很小的数,小数点后面很多位都行;在深入一点,就可以计算很大的数的乘法(按笔算的乘法过程来),计算器没法实现,这样算法就可以派上用场。当然,pythoon有很多强大的模块也可做到。

最近有点忙过头了,但是想想又没做什么。。。。真真是时间都去哪了?今早放洗衣机里的衣服一直没拿出来,还是刚才赶回去拿出来了,立马回来上课。今天上完晚课,就原地开始写文章了,还好没晚太久。明天空了(可能就这一周了,两个老师都想要周五没课的时间,估计是保不住了),我会好好整理下,刚开学过得稀里糊涂的。

还是那样,我一如既往的乐于帮助大家——微信、简书:Dkider。语句千万条,正确第一条。代码不规范,手指两行泪。

2mMryi.jpg Dkider

这是这首诗的后两句。只能说李白在哪里都很厉害。我李白贼秀。。。

我醉欲眠卿且去,明朝有意抱琴来。 ——李白《山中与幽人对酌》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值