今天帶來一道來自互聯網大廠(字節、騰訊、微軟、蘋果等) 面試題 Leetcode 61. 旋轉鏈表,提供 "虛擬頭節點 + 雙指針" 的解題思路,采用 "動圖" 的方式進行層層剖析,供大家參考,希望對大家無論是刷題還是面試都有所幫助。
61. 旋轉鏈表
描述
給你一個鏈表的頭節點 head ,旋轉鏈表,將鏈表每個節點向右移動 k 個位置。
解題思路
思考
考慮以下幾種情況:
特殊情況
- 鏈表為空或只有一個節點;
- k 的值為 0 或者為鏈表長度 L 的整數倍(N > 0)。
一般情況
- 鏈表至少有兩個節點且 k 既不等於 0 也不等於 L 的整數倍。
思路
- 特殊情況
- 鏈表為空或只有一個節點,只要返回頭節點即可;
- 判斷 k == 0,如果等於 0,則直接返回頭節點,否則求鏈表長度 L,再判斷 k == NL,如果等於,也可直接返回。
- 一般情況
- 采用 虛擬頭節點 + 雙指針 的方法,具體如下栗子分析。
舉栗
以鏈表 1->2->3->4->5,k = 2 為栗子,如下圖所示。
增加虛擬頭節點,設置兩根快慢指針 fast/slow 指向它;
先讓快指針 fast 向前移動 k 步,慢指針 slow 保持不動;
快慢指針 fast/slow 同時向前移動,直至快指針指向尾節點;
讓快指針 fast 指向的節點指向鏈表的頭節點;
將慢指針 slow 指向的節點的下一節點設置為新鏈表的頭節點;
將慢指針 slow 指向的節點設置為新鏈表的尾節點 slow->next = null;
旋轉原鏈表后得到新鏈表。
完整動圖
反思
- 如何找到旋轉之后得到的新鏈表的頭節點?
采用 雙指針 中的 快慢指針 。
- 設置虛擬頭節點的作用?
本題設置 虛擬頭節點 的作用是找到 新鏈表的頭節點和尾節點。通過 快慢指針 去尋找。
Show me the Code
C++

1 ListNode* rotateRight(ListNode* head, int k) { 2 /* 特殊情況判斷 */ 3 if (head == nullptr || head->next == nullptr || k == 0) { 4 return head; 5 } 6 7 /* 增加虛擬頭節點 */ 8 ListNode* dummy = new ListNode(0); 9 dummy->next = head; 10 11 /* 獲取鏈表長度 */ 12 int len = 0; 13 for (ListNode* node = head; node != nullptr; node = node->next) { 14 len++; 15 } 16 17 k %= len; 18 /* 判斷 k 是否是 len 的整數倍 */ 19 if (k == 0) { 20 return head; 21 } 22 23 /* 獲取新鏈表的頭尾節點 */ 24 ListNode *fast = dummy, *slow = dummy; 25 for (int i = 0; i < k; ++i) { 26 fast = fast->next; 27 } 28 while (fast->next != nullptr) { 29 fast = fast->next; 30 slow = slow->next; 31 } 32 fast->next = head; 33 head = slow->next; 34 slow->next = nullptr; 35 36 /* 釋放虛擬頭節點 */ 37 delete dummy; 38 39 return head; 40 }
java

1 ListNode rotateRight(ListNode head, int k) { 2 if (k == 0 || head == null || head.next == null) { 3 return head; 4 } 5 6 ListNode dummy = new ListNode(0); 7 dummy.next = head; 8 9 int len = 0; 10 for (ListNode node = head; node != null; node = node.next) { 11 len++; 12 } 13 14 k %= len; 15 if (k == 0) { 16 return head; 17 } 18 19 ListNode fast = dummy, slow = dummy; 20 for (int i = 0; i < k; ++i) { 21 fast = fast.next; 22 } 23 while (fast.next != null) { 24 fast = fast.next; 25 slow = slow.next; 26 } 27 fast.next = head; 28 head = slow.next; 29 slow.next = null; 30 31 return head; 32 }