前言
有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