LeetCode 61——旋转链表
生活随笔
收集整理的這篇文章主要介紹了
LeetCode 61——旋转链表
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 題目
2. 解答
2.1. 方法一
將鏈表每個節點向右移動 1 個位置,其實就是讓鏈表最后一個結點指向第一個結點。
因此,向右移動 k 個位置就重復上述過程 k 次即可。
然后,我們注意到,若鏈表有 n 個結點,則移動 n 次后就還是原鏈表。
原始鏈表 1->2->3->NULL 向右旋轉 1 步: 3->1->2->NULL 向右旋轉 2 步: 2->3->1->NULL 向右旋轉 3 步: 1->2->3->NULL實際上,若鏈表有 n 個結點,我們只需要移動 n % k 次即可。
確定鏈表有多少個結點,我們則可以用快慢指針法。
- 偶數個結點時,結點個數等于 i * 2。
- 奇數個結點時,結點個數等于 i * 2 + 1。
2.2. 方法二
上面的算法中每次將鏈表結點向右移動 1 個位置的時候,我們都要遍歷一次鏈表,效率較低。
針對鏈表 1->2->3->4->5->NULL,如果要將鏈表每個結點向右移動 2 個位置,那倒數第 2 個結點就是旋轉后新鏈表的起始位置;如果要將鏈表每個結點向右移動 3 個位置,那倒數第 3 個結點就是旋轉后新鏈表的起始位置;而如果要將鏈表每個結點向右移動 33 個位置,那倒數第 3 個結點就是旋轉后新鏈表的起始位置。
更一般的情況下,若鏈表長度為 n,移動次數為 k,旋轉后鏈表的起始位置就是原鏈表倒數第 k % n 個結點。
在上面的例子中,假設新鏈表的起始位置是結點 4,那鏈表就被分成了兩部分。1->2->3 和 4->5->NULL,我們要做的就是把 1->2->3 拼接在 4->5->NULL 后即可。
實現思路是這樣的:
我們先通過快慢指針確定鏈表長度 n,然后找到旋轉后鏈表起始位置的上一個結點,記為 new_head_last,然后從起始位置 new_head 開始向后遍歷,當到達 NULL 時,將 head 指向的頭結點拼接在 new_head 后面,然后再將新鏈表的最后一個結點也即 new_head_last 后面置為 NULL 即可。 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:ListNode* rotateRight(ListNode* head, int k) {if (head == NULL || head->next == NULL) return head;int node_num = 0; // 鏈表的結點個數int mid_num = 0;ListNode* slow = head;ListNode* fast = head;// 利用快慢指針確定鏈表的結點總個數while(fast && fast->next){slow = slow->next;fast = fast->next->next;mid_num++;}if (fast) // 奇數個結點{node_num = mid_num * 2 + 1;}else // 偶數個結點{node_num = mid_num * 2;}// 若鏈表有 K 個結點,向右移動 K 個位置就還是原鏈表// 因此我們只需要移動 K % node_num 次即可if (k % node_num == 0) return head;else k = k % node_num;int which_node_is_new = 0; // 旋轉后的頭結點是第幾個節點ListNode* new_head = NULL;ListNode* new_head_last = NULL;// 查找旋轉后頭結點的上一個結點// 此時 slow 指針指向中間結點,分為在 slow 前還是在 slow 后which_node_is_new = node_num - k; if (which_node_is_new > node_num / 2){new_head_last = slow;for (int i = 0; i < which_node_is_new - mid_num - 1; i++){new_head_last = new_head_last->next;}}else{new_head_last = head;for (int i = 1; i < which_node_is_new; i++){new_head_last = new_head_last->next;} }new_head = new_head_last->next;ListNode* temp = new_head;while (temp->next){temp = temp->next;}temp->next = head;new_head_last->next = NULL;return new_head;} };獲取更多精彩,請關注「seniusen」!
總結
以上是生活随笔為你收集整理的LeetCode 61——旋转链表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 温故而知新 Vue 原来也有this.$
- 下一篇: 实时计算Flink——产品安全