LeetCode 61. Rotate List
每日題。其實我不確定這算不算雙指標,應該勉強算吧。
題目
輸入一linked list的head,將其向右旋轉k次。
head = [1,2,3,4,5], k = 2
rotated = [4,5,1,2,3]
解法
首先過濾幾種不用更動的狀況:空串列、長度一串列或是k=0,直接回傳head。
再來計算整個串列長度size,方便之後旋轉。再拿k模size檢查一次看是否餘0,若是則可直接回傳。
把原串列分為前後兩部分,前面長度為size-k,後面長度為k。所以從head開始向後前進size-k-1次可以抵達newHead,保存位置並切斷連結。
最後再從newHead走到尾端,接上原本的head就成功旋轉了。
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head or not head.next or k == 0:
return head
size = 0
curr = head
while curr:
size += 1
curr = curr.next
k %= size
if k == 0:
return head
move = size-k
curr = head
for _ in range(move-1):
curr = curr.next
newHead = curr.next
curr.next = None
curr = newHead
while curr.next:
curr = curr.next
curr.next = head
return newHead
參考別人解法,加上一個dummy head會更好處理。
拿dummy接上head,所有遍歷都從dummy開始。
一樣先計算長度,只是判斷條件改為後方還有節點時才前進,這樣可以停在最後一點,而不是null上。
size模k跟之前一樣。
再來就是其中精髓:數完長度馬上把串列頭尾接上,之後就不必再跑一次了!
最後是找切斷點mid,從dummy開始數,多一個點,所以size-k就可以,剛好抵銷-1。最後保存newHead,切斷連結回傳即可。
class Solution:
def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
if not head or not head.next or k == 0:
return head
dummy = ListNode(next=head)
size = 0
tail = dummy
while tail.next:
size += 1
tail = tail.next
k %= size
if k == 0:
return head
tail.next = head
mid = dummy
for _ in range(size-k):
mid = mid.next
newHead = mid.next
mid.next = None
return newHead