【LeetCode題解】61_旋轉連結串列(Rotate-List)
阿新 • • 發佈:2018-11-06
目錄
描述
給定一個連結串列,旋轉連結串列,將連結串列每個節點向右移動 k 個位置,其中 k 是非負數。
示例 1:
輸入: 1->2->3->4->5->NULL, k = 2 輸出: 4->5->1->2->3->NULL 解釋: 向右旋轉 1 步: 5->1->2->3->4->NULL 向右旋轉 2 步: 4->5->1->2->3->NULL
示例 2:
輸入: 0->1->2->NULL, k = 4
輸出: 2->0->1->NULL
解釋:
向右旋轉 1 步: 2->0->1->NULL
向右旋轉 2 步: 1->2->0->NULL
向右旋轉 3 步: 0->1->2->NULL
向右旋轉 4 步: 2->0->1->NULL
解法:雙指標
思路
求解這道題等價於找到連結串列倒數第 k 個節點,然後將之前的所有節點放到連結串列的尾部,形成一個新的連結串列,相當於 LeetCode 第 19 題的進階版。
對於尋找單向連結串列的倒數第 \(k\)
- 令指標
p1
和指標p2
均指向表頭,然後讓指標p2
跳轉 \(k - 1\) 次,此時指標p2
處於連結串列的第 \(k\) 個節點
- 接著,讓兩個指標同時向連結串列尾部跳轉,直到指標
p2
處於連結串列的尾部,此時,指標p1
指向的節點正是連結串列的倒數第 \(k\) 個節點
在找到倒數第 \(k\) 個節點後,只需要將指標 p2
指向連結串列頭 head
、指標 p1
的前一個節點的 next
指標指向 null
,最後指標 p1
就是新的連結串列的表頭。
值得注意的是,在這道題中,我們需要找到的是連結串列的倒數第 \(k+1\)
next
指標進行操作(指向 null
)。同樣地,也需要注意一些邊界情況,比如表頭 head
為空,k
大於連結串列長度等。
Java 實現
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
// 邊界情況處理
if (head == null) {
return head;
}
// 統計連結串列長度並對k進行取餘操作
int length = 1;
ListNode tmp = head;
while (tmp.next != null) {
tmp = tmp.next;
++length;
}
k = k % length;
if (k == 0) {
return head;
}
// 尋找倒數第k+1個節點
ListNode p1 = head, p2 = head;
for (int i = 0; i < k; ++i) {
p2 = p2.next;
}
while (p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
// 旋轉連結串列
ListNode newHead = p1.next;
p1.next = null;
p2.next = head;
return newHead;
}
}
// Runtime: 6 ms
// Your runtime beats 100.00 % of java submissions.
Python 實現
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def rotateRight(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
# 邊界情況處理
if not head:
return head
# 統計連結串列的長度並對k進行取餘操作
tmp, n = head, 1
while tmp.next:
tmp, n = tmp.next, n + 1
k = k % n
if k == 0:
return head
# 找到倒數第k+1個節點
p1, p2 = head, head
for i in range(k):
p2 = p2.next
while p2.next:
p1 = p1.next
p2 = p2.next
# 旋轉連結串列
new_head = p1.next
p1.next, p2.next = None, head
return new_head
# Runtime: 44 ms
# Your runtime beats 99.11 % of python3 submissions.
複雜度分析
- 時間複雜度:\(O(n)\),其中 \(n\) 表示連結串列的長度。首先需要迭代 \(n\) 次找出連結串列的長度,接著讓指標
p2
迭代 \(k\) 次到達第 \(k+1\) 個節點的位置,最後還需要迭代 \(n-(k+1)\) 次使得兩個指標一個指向連結串列尾部,一個指向倒數第 \(k+1\) 個節點,而迭代所執行的操作的時間複雜度都是 \(O(1)\) 的,所以最後總的時間複雜度是 \(O(n)\) 的 - 空間複雜度:\(O(1)\)