前言
有Python基础
有数据结构单链表基础,不清楚的参考前面的博客
链接: https://blog.csdn.net/sf9898/article/details/104946291
问题描述
给出两个非空的链表,用来表示两个非负的整数,他们的位数是按逆序存储的,
并且每一个节点都只能存储一个数字。如果将这两个数相加,则会返回一个新的链表
来表示他们的和。可以假设除了数字0之外,这两个数都不会以0开头。
输入输出这一块划重点,这里的输入输出是比较抽象的,大致意思对了就行,不是牛客网那种格式化输入。
输入(1 -> 6 -> 4)+ (3 -> 1 -> 2)
输出 (4 -> 7 -> 6)
原因是 461+213 = 674
分析及实现
part1.分析与定义
题目要求是用的链表,那么首先先定义链表类。
关于数据的合法性:一般不会为难人,给的都会是合法数据,不用判断负数。也不用纠结要是节点存不是一个数字的情况。输入的都只能是合法的字符。
关于输入,怎么输入就怎么存,也就是说输入也是逆序的。
class Node(object):
def __init__(self, item):
self.item = item
self.next = None
class Link(object):
def __init__(self):
self.__head = None
接下来再写几个可能会用到的函数。比如插入和删除等。题目中说位数是按照逆序存储的,那么假设从尾部插入,第一个数进来1,第二次进来6,第三次进来4,那么根据这个想法,得到的链表从头到尾是不是164,是不是符合题意?实际上表示的数是461,实现了逆序存储,因此在插入这一块应该写尾部插入。
def addBack(self, item):
node = Node(item)
if self.__head is None:
self.__head = node
return
cur = self.__head
pre = None
while cur:
pre = cur
cur = cur.next
pre.next = node
def isEmpty(self):
return self.__head is None
# 定义一个遍历函数用来验证
def travel(self):
cur = self.__head
while cur:
print(cur.item, end=' ')
cur = cur.next
print('')
ok ,再考虑下删除和相加的事。如果直接提取两个数相加可以吗?小数字貌似可以,但是大的数字呢?看看自己的计算机是几位的。一万个、一千个1也是合法数据,照样得算,照样得有结果。因此不能采用提取各个节点的item然后拼起来形成一个数相加的方法。应该回归到小学数学,回到最初的起点。第一个节点是个位,后面的是十位百位…那么一个一个删除提取出来做加法,有进位的话要注意。因此在Link类里面应该有删除的方法,而且这个方法还要有返回值(不然怎么算)。
def removeFront(self):
# 返回值是一个节点的item,空节点的话返回0,这个函数要做到删除,并且有返回值
cur = self.__head
if cur:
self.__head = self.__head.next
return cur.item
else:
return 0
上面代码的写法是为了防止三位数加两位数的这种类似的情况。
“如果将这两个数相加,则会返回一个新的链表来表示他们的和。”从题目的这点要求可以看出,我们需要设置一个函数,接收的参数是两个链表的对象(当然,写别的好像也行,只要能实现)。返回值是一个新的链表,当然,这个链表依旧是逆序存储。
def addTwoNum(l1, l2):
# 参数是两个链表的对象,只要两个链表都不是空那就可以算,3位加2位的话,第二个数的百位就当做0
ll = Link()
addNum = 0 # 进位
while l1.isEmpty() == False or l2.isEmpty() == False:
temp = l1.removeFront() + l2.removeFront() + addNum
addNum = 0
if temp >= 10:
# 大于等于10要进位哦
addNum = 1
temp = temp - 10
ll.addBack(temp) # 存进去
return ll
part2.完整代码测试一下
# 给出两个非空的链表,用来表示两个非负的整数,他们的位数是按逆序存储的, --一般给的都会是合法数据,不会为难人
# --这一点说明从头到尾应该是164(实际上这个链表表示的数是461) 312(213) 476(674)
# 第一次输入的数是1,之后6,然后4,因此是尾部插入
# 并且每一个节点都只能存储一个数字。如果将这两个数相加,则会返回一个新的链表 --item只能存一个数
# 来表示他们的和。可以假设除了数字0之外,这两个数都不会以0开头。
# 相加怎么进行?直接取出来加??这样是不行的,因为PC的计算范围是有限的,想想自己的电脑是几位的机子。
# 一千个1加上一千个1理应是一千个2,这样的数是合法的。因此应当回归到最初的起点,用最原始的小学的数学计算去做。
# 先取出个位数,即开头,然后十位百位...但是这里又要注意,万一两个数的位数是不一样的呢?
# 从取数字的角度来讲,应该是要取开头
# 输入(1 -> 6 -> 4)+ (3 -> 1 -> 2)
# 输出 (4 -> 7 -> 6)
# 原因是 461+213 = 674
class Node(object):
def __init__(self, item):
self.item = item
self.next = None
class Link(object):
def __init__(self):
self.__head = None
def isEmpty(self):
return self.__head is None
def addBack(self, item):
node = Node(item)
if self.__head is None:
self.__head = node
return
cur = self.__head
pre = None
while cur:
pre = cur
cur = cur.next
pre.next = node
def removeFront(self):
# 返回值是一个节点的item,空节点的话返回0,这个函数要做到删除,并且有返回值
cur = self.__head
if cur:
self.__head = self.__head.next
return cur.item
else:
return 0
# 定义一个遍历函数用来验证
def travel(self):
cur = self.__head
while cur:
print(cur.item, end=' ')
cur = cur.next
print('')
def addTwoNum(l1, l2):
# 参数是两个链表的对象,只要两个链表都不是空那就可以算,3位加2位的话,第二个数的百位就当做0
ll = Link()
addNum = 0 # 进位
while l1.isEmpty() == False or l2.isEmpty() == False:
temp = l1.removeFront() + l2.removeFront() + addNum
addNum = 0
if temp >= 10:
# 大于等于10要进位哦
addNum = 1
temp = temp - 10
ll.addBack(temp) # 存进去
return ll
def main():
l1 = Link()
l2 = Link()
N1 = int(input()) # 这个用来接收用户的输入,代表第一个数的位数(第一个链表的节点数)
# 接下来输入1 6 4(类似这样子),假设是这样,那么N1 = 3,下面循环三次,接收三个输入,尾插三次
for i in range(N1):
l1.addBack(int(input()))
N2 = int(input()) # 第二个数的位数
for i in range(N2):
l2.addBack(int(input()))
# 写到这里可以利用遍历函数初步验证添加是否成功、是否逆序存储
l1.travel() # 1 6 4
l2.travel() # 3 1 2
# 希望调用一个函数直接计算出结果并返回一串链表
ll = addTwoNum(l1, l2)
ll.travel()
if __name__ == '__main__':
main()
part3.根据代码中的设置,输入数据验证
test1
输入:
3
1
2
3
2
4
5
输出:
1 2 3
4 5
5 7 3
输入的第一个数是N1,是第一个数的位数。接下来三个数是123(表示的是321,因为链表里面逆序存储)。之后是2,是N2,是第二个数的位数。接下来两个数是45,表示54。因此在进行加法之后,321+54 = 375,代码中ll.travel()的结果应是5 7 3。结果如下。
test2
输入:
3
1
6
4
3
3
1
2
输出:
1 6 4
3 1 2
4 7 6
test3
为了验证进位的情况,再设置了一组测试数据,7 3 1(实际表示137),4 6(实际是64),137+64=201,因此结果输出应该是1 0 2
输入:
3
7
3
1
2
4
6
输出:
7 3 1
4 6
1 0 2