python什么是交换算法_python算法-015将链表元素两两交换元素(交换值、就地翻转)...
大鵬一日同風起,扶搖直上九萬里。
假令風歇時下來,猶能簸卻滄溟水。
世人見我恒殊調,聞余大言皆冷笑。
宣父猶能畏后生,丈夫未可輕年少。
——李白《上李邕》
在現代,別人對你的文章冷嘲熱諷,你來一句:“你行你上啊!”他可能就沒脾氣了。但是要換李白,他真的會上,因為他真的行!
題目描述:將鏈表的每兩個節點翻轉。不允許用新的節點。
例如:
給定鏈表Head->1->2->3->4->5->7->7->8
反轉為鏈Head->2->1->4->3->7->5->8->7
這題是為了明天的題目做鋪墊的,先來分析下這個題:本質上還是操作鏈表,之前我們做過類似的。不過,這次是翻轉節點,節點有兩個屬性data和next,交換兩個節點的值就可以完成了,這樣不需要將節點位置改變。這太簡單了,就像a=1,b=2,交換a,b的值一樣那么簡單,只需要用一個中間值tmp來保存就行:tmp=a a=b b=tmp。主要的問題就是如何遍歷的問題,這也是個不是問題的問題。用一個指針即可完成,但是對于明天的題,并沒有太大幫助。
下面來看利用next屬性,如何做:
利用next屬性必然會改變節點的位置,也就是鏈表結構會變,先來看看怎樣改變
主兩個指針,更好理解
圖中我用紅筆標出了操作順序1、2、3、4:先pre->fast,然后fast->slow,最后slow->next,這里為什么會先把next->fast.next:因為在第二步時,得保存后面的鏈表,不然會丟失,這與a.b交換值是一個道理。這里的順序也可以換成1、2、4、3,兩個效果是一樣的。
這里有一個注意的地方就是每次的循環條件:宗旨就是當后面的節點不夠一組進行交換時,退出循環。但是如何知道后面不夠一組呢?先來看下代碼。
下面代碼實現:
def function(head):
#判斷鏈表是否為空,為空返回
if head.next is None or head.next.next is None:
return head
pre=head # 指向slow的前驅節點
slow=head.next
fast=slow.next
#slow和fast為相鄰的節點
#next=fast.next
# 這里的循環條件要注意
# 鏈表的長度可能為奇數,也可能是偶數
# 每次四個指針會變換,因為是先操作再迭代下一組
# 再迭變換完后,如果fast指針后面只有一個元素,或者沒有元素,這時
# 后面的無法再進行翻轉,所以應該出循環,正常應該做完在判斷的,
# 這里只能符合的才操作,因為用的指針多了一個。
while fast.next is not None and fast.next.next is not None:
next = fast.next #保存鏈表,因為要斷開
pre.next=fast
fast.next=slow
slow.next=next
# # 上面的四句做的操作,見圖
pre=slow
slow=next
fast=slow.next
#因為面的判斷條件,最后一組,我們并沒有翻轉,這里操作下
next = fast.next
pre.next = fast
fast.next = slow
slow.next = next
return head
這里我用while fast.next is not None and fast.next.next is not None,這一句看起來很臃腫。
一組
這里我用了四個指針,鏈表的長度可能為奇數,也可能是偶數,每次四個指針會變換,因為是先操作再迭代下一組,在變換完后,如果fast指針后面只有一個元素,或者沒有元素,這時后面的無法再進行翻轉,所以應該出循環,按分析應該做完在判斷的,但是因為涉及到一個next指針,每次都得確定還有next,才能操作,不然會報錯,這里我還沒找到一個好的解釋辦法。要注意的是,最后一組沒有換位置,可以把最后的四行語句注釋掉,看看結果就知道了。
image.png
鑒于此,我把指針減少了,只用一個主指針cur,用(cur,cur.next)這樣一組來代替slow,fast。
這樣的好處是,不用考慮fast是否有next.next,只看cur就行。操作是一樣的:
image.png
代碼實現:
def function(head):
if head is None or head.next is None:
return head
cur=head.next#當前遍歷節點
pre=head#當前遍歷節點的前驅節點
next=None#當前節點后繼節點的后繼節點
# 這里的循環條件可能不太一樣,因為省掉了fast,所以考慮的東西就會變少。
while cur is not None and cur.next is not None:
next=cur.next.next
pre.next=cur.next
#這里可能一看不太好理解
# (cur.next).next
# 這樣把cur.next看做一個節點,也就是之前的fast
cur.next.next=cur
cur.next=next
pre=cur
cur=next
return head
循環條件變了,我將他們放在一個文件里了,如果后者沒問題,就可以把變換的鏈表變回去:
if __name__ == '__main__':
head = creatLink(6)
print("head:")
cur = head.next
while cur != None:
print(cur.data)
cur = cur.next
head = function_1(head)
print("\nAfterReverse_1:") # 這是用slow和fast的
cur = head.next
while cur != None:
print(cur.data)
cur = cur.next
head = function_2(head) # 這是cur
print("\nAfterReverse_2:")
cur = head.next
while cur != None:
print(cur.data)
cur = cur.next
輸出結果:
image.png
全部代碼:
import random
class LNode:
def __init__(self,arg):
self.data=arg
self.next=None
"""
題目描述:
給定鏈表Head->1->2->3->4->5->7->7->8
反轉為鏈Head->2->1->4->3->7->5->8->7
要求:
方法:只用一個cur,用pre和next輔助反轉。
"""
def creatLink(x):
i = 1
head = LNode(None)
tmp = None
cur = head
while i <= x:
n = random.randint(1, 9)
tmp = LNode(n)
cur.next = tmp
cur = tmp
i += 1
return head
#
#雙指針法
def function_1(head):
#判斷鏈表是否為空,為空返回
if head.next is None or head.next.next is None:
return head
pre=head # 指向slow的前驅節點
slow=head.next
fast=slow.next
#slow和fast為相鄰的節點
#next=fast.next
# 這里的循環條件要注意
# 鏈表的長度可能為奇數,也可能是偶數
# 每次四個指針會變換,因為是先操作再迭代下一組
# 再迭變換完后,如果fast指針后面只有一個元素,或者沒有元素,這時
# 后面的無法再進行翻轉,所以應該出循環,正常應該做完在判斷的,
# 這里只能符合的才操作,因為用的指針多了一個。
while fast.next is not None and fast.next.next is not None:
next = fast.next #保存鏈表,因為要斷開
pre.next=fast
fast.next=slow
slow.next=next
# # 上面的四句做的操作,見圖
pre=slow
slow=next
fast=slow.next
#因為面的判斷條件,最后一組,我們并沒有翻轉,這里操作下
next = fast.next
pre.next = fast
fast.next = slow
slow.next = next
return head
def function_2(head):
if head is None or head.next is None:
return head
cur=head.next#當前遍歷節點
pre=head#當前遍歷節點的前驅節點
next=None#當前節點后繼節點的后繼節點
# 這里的循環條件可能不太一樣,因為省掉了fast,所以考慮的東西就會變少。
while cur is not None and cur.next is not None:
next=cur.next.next
pre.next=cur.next
#這里可能一看不太好理解
# (cur.next).next
# 這樣把cur.next看做一個節點,也就是之前的fast
cur.next.next=cur
cur.next=next
pre=cur
cur=next
return head
if __name__ == '__main__':
head = creatLink(6)
print("head:")
cur = head.next
while cur != None:
print(cur.data)
cur = cur.next
head = function_1(head)
print("\nAfterReverse_1:")
cur = head.next
while cur != None:
print(cur.data)
cur = cur.next
head = function_2(head)
print("\nAfterReverse_2:")
cur = head.next
while cur != None:
print(cur.data)
cur = cur.next
鋪墊就到這里,明天的題目是:
將鏈表以k個一組翻轉,不足k個也翻轉,
給定鏈表Head->1->2->3->4->5->7->7->8
k=3
反轉為鏈Head->3->2->1->7->5->4->8->7
會嗎?
今天就這樣,更多題目見GitHub,簡書、微信:DKider。
Data Knowledge idea(我故意打的r),這是我寒假想的名字,還挺好,之前沒有什么實際意義,現在它有了!
我會盡量加快寫的速度,我還要留時間學其他的知識。加油吧!
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的python什么是交换算法_python算法-015将链表元素两两交换元素(交换值、就地翻转)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nimbus java_Java程序设置
- 下一篇: java研发自测报告_开发自测方法探讨