每K個一組反轉單鏈表
阿新 • • 發佈:2021-06-21
這是laluladong系列學習的一部分。
同步發表於我的個人站點:每K個一組反轉單鏈表
題目:
給你一個連結串列,每 k 個節點一組進行翻轉,請你返回翻轉後的連結串列。
k 是一個正整數,它的值小於或等於連結串列的長度。
如果節點總數不是 k 的整數倍,那麼請將最後剩餘的節點保持原有順序。
labuladong的解法: https://labuladong.gitee.io/algo/2/17/17/
leetcode官方解法: https://leetcode-cn.com/problems/reverse-nodes-in-k-group/
我把兩種解法的程式碼實現都寫在下面的程式碼裡面了。
關於兩個教程的一些比較:
- labuladong的教程相對於leetcode來說更容易理解
- labuladong的教程說是迭代解法,但實際上還是用到了遞迴,所以在效能上要比leetcode的解法差一些
- leetcode的解題思路更具有引導的作用,比如在head節點前面認為創造一個pre節點可以避免特判,雖然labuladong也是這麼做的,但是沒有明說出來,新手可能不容日get到那個點
整體上來說,建議先看labuladong的教程,實際把程式碼實現一邊,然後再好好看看leetcode官方解法,尤其是解題思路。
leetcode解法中反轉部分子連結串列的地方關於prev節點的處理方法有一點還沒理解,在程式碼中做了註釋,如果有了解的大神希望可以通過評論指導我一下
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: ## laluladong 解法(迭代) # def reverse(self, head: ListNode, tail: ListNode) -> ListNode: # pre = None # cur = head # nxt = head # while cur != tail: # nxt = cur.next # cur.next = pre # pre = cur # cur = nxt # return pre # def reverseKGroup(self, head: ListNode, k: int) -> ListNode: # if head == None: # return head # a = head # b = head # for item in range(k): # if b != None: # b = b.next # else: # return head # newHead = self.reverse(a, b) # a.next = self.reverseKGroup(b, k) # return newHead ## 官方解法 # 翻轉一個子連結串列,並且返回新的頭與尾 def reverse(self, head: ListNode, tail: ListNode): prev = tail.next # 這裡給prev賦值為None也可以,不影響結果,但是效能會差,為什麼? p = head while prev != tail: nex = p.next p.next = prev prev = p p = nex return tail, head def reverseKGroup(self, head: ListNode, k: int) -> ListNode: hair = ListNode(0) hair.next = head pre = hair while head: # 這個迴圈會反轉整個連結串列,替代了laluladong迭代解法中的遞迴呼叫 tail = pre # 檢視剩餘部分長度是否大於等於 k for i in range(k): tail = tail.next if not tail: return hair.next nex = tail.next head, tail = self.reverse(head, tail) # 把子連結串列重新接回原連結串列 pre.next = head tail.next = nex pre = tail # 此時的tail是後面一段子連結串列的hair(也就是pre) head = tail.next return hair.next