日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode 61——旋转链表

發布時間:2025/6/17 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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。
/*** 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; // 鏈表的結點個數ListNode* slow = head;ListNode* fast = head;// 利用快慢指針確定鏈表的結點總個數while(fast && fast->next){slow = slow->next;fast = fast->next->next;node_num++;}if (fast) // 奇數個結點{node_num = node_num * 2 + 1;}else // 偶數個結點{node_num = node_num * 2;}// 若鏈表有 K 個結點,向右移動 K 個位置就還是原鏈表// 因此我們只需要移動 K % node_num 次即可if (k % node_num == 0) return head;else k = k % node_num;ListNode *temp = head;ListNode *last_node = NULL;for (int i = 0; i < k; i++){// 向右移動 1 個位置就是讓最后一個結點指向第一個結點// 先找到倒數第二個結點while (temp->next->next){temp = temp->next;}// 最后一個結點指向第一個結點,倒數第二個節點指向 NULLlast_node = temp->next;temp->next = NULL;last_node->next = head;head = last_node;temp = head;}return head;} };

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——旋转链表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。