日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

LeetCode 61——旋转链表

發(fā)布時(shí)間:2025/6/17 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode 61——旋转链表 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 題目

2. 解答

2.1. 方法一

將鏈表每個(gè)節(jié)點(diǎn)向右移動(dòng) 1 個(gè)位置,其實(shí)就是讓鏈表最后一個(gè)結(jié)點(diǎn)指向第一個(gè)結(jié)點(diǎn)。

因此,向右移動(dòng) k 個(gè)位置就重復(fù)上述過(guò)程 k 次即可。

然后,我們注意到,若鏈表有 n 個(gè)結(jié)點(diǎn),則移動(dòng) n 次后就還是原鏈表。

原始鏈表 1->2->3->NULL 向右旋轉(zhuǎn) 1 步: 3->1->2->NULL 向右旋轉(zhuǎn) 2 步: 2->3->1->NULL 向右旋轉(zhuǎn) 3 步: 1->2->3->NULL

實(shí)際上,若鏈表有 n 個(gè)結(jié)點(diǎn),我們只需要移動(dòng) n % k 次即可。

確定鏈表有多少個(gè)結(jié)點(diǎn),我們則可以用快慢指針?lè)ā?/p>

  • 偶數(shù)個(gè)結(jié)點(diǎn)時(shí),結(jié)點(diǎn)個(gè)數(shù)等于 i * 2。

  • 奇數(shù)個(gè)結(jié)點(diǎn)時(shí),結(jié)點(diǎn)個(gè)數(shù)等于 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; // 鏈表的結(jié)點(diǎn)個(gè)數(shù)ListNode* slow = head;ListNode* fast = head;// 利用快慢指針確定鏈表的結(jié)點(diǎn)總個(gè)數(shù)while(fast && fast->next){slow = slow->next;fast = fast->next->next;node_num++;}if (fast) // 奇數(shù)個(gè)結(jié)點(diǎn){node_num = node_num * 2 + 1;}else // 偶數(shù)個(gè)結(jié)點(diǎn){node_num = node_num * 2;}// 若鏈表有 K 個(gè)結(jié)點(diǎn),向右移動(dòng) K 個(gè)位置就還是原鏈表// 因此我們只需要移動(dòng) 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++){// 向右移動(dòng) 1 個(gè)位置就是讓最后一個(gè)結(jié)點(diǎn)指向第一個(gè)結(jié)點(diǎn)// 先找到倒數(shù)第二個(gè)結(jié)點(diǎn)while (temp->next->next){temp = temp->next;}// 最后一個(gè)結(jié)點(diǎn)指向第一個(gè)結(jié)點(diǎn),倒數(shù)第二個(gè)節(jié)點(diǎn)指向 NULLlast_node = temp->next;temp->next = NULL;last_node->next = head;head = last_node;temp = head;}return head;} };

2.2. 方法二

上面的算法中每次將鏈表結(jié)點(diǎn)向右移動(dòng) 1 個(gè)位置的時(shí)候,我們都要遍歷一次鏈表,效率較低。

針對(duì)鏈表 1->2->3->4->5->NULL,如果要將鏈表每個(gè)結(jié)點(diǎn)向右移動(dòng) 2 個(gè)位置,那倒數(shù)第 2 個(gè)結(jié)點(diǎn)就是旋轉(zhuǎn)后新鏈表的起始位置;如果要將鏈表每個(gè)結(jié)點(diǎn)向右移動(dòng) 3 個(gè)位置,那倒數(shù)第 3 個(gè)結(jié)點(diǎn)就是旋轉(zhuǎn)后新鏈表的起始位置;而如果要將鏈表每個(gè)結(jié)點(diǎn)向右移動(dòng) 33 個(gè)位置,那倒數(shù)第 3 個(gè)結(jié)點(diǎn)就是旋轉(zhuǎn)后新鏈表的起始位置。

更一般的情況下,若鏈表長(zhǎng)度為 n,移動(dòng)次數(shù)為 k,旋轉(zhuǎn)后鏈表的起始位置就是原鏈表倒數(shù)第 k % n 個(gè)結(jié)點(diǎn)

在上面的例子中,假設(shè)新鏈表的起始位置是結(jié)點(diǎn) 4,那鏈表就被分成了兩部分。1->2->3 和 4->5->NULL,我們要做的就是把 1->2->3 拼接在 4->5->NULL 后即可。

實(shí)現(xiàn)思路是這樣的:

我們先通過(guò)快慢指針確定鏈表長(zhǎng)度 n,然后找到旋轉(zhuǎn)后鏈表起始位置的上一個(gè)結(jié)點(diǎn),記為 new_head_last,然后從起始位置 new_head 開(kāi)始向后遍歷,當(dāng)?shù)竭_(dá) NULL 時(shí),將 head 指向的頭結(jié)點(diǎn)拼接在 new_head 后面,然后再將新鏈表的最后一個(gè)結(jié)點(diǎn)也即 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; // 鏈表的結(jié)點(diǎn)個(gè)數(shù)int mid_num = 0;ListNode* slow = head;ListNode* fast = head;// 利用快慢指針確定鏈表的結(jié)點(diǎn)總個(gè)數(shù)while(fast && fast->next){slow = slow->next;fast = fast->next->next;mid_num++;}if (fast) // 奇數(shù)個(gè)結(jié)點(diǎn){node_num = mid_num * 2 + 1;}else // 偶數(shù)個(gè)結(jié)點(diǎn){node_num = mid_num * 2;}// 若鏈表有 K 個(gè)結(jié)點(diǎn),向右移動(dòng) K 個(gè)位置就還是原鏈表// 因此我們只需要移動(dòng) K % node_num 次即可if (k % node_num == 0) return head;else k = k % node_num;int which_node_is_new = 0; // 旋轉(zhuǎn)后的頭結(jié)點(diǎn)是第幾個(gè)節(jié)點(diǎn)ListNode* new_head = NULL;ListNode* new_head_last = NULL;// 查找旋轉(zhuǎn)后頭結(jié)點(diǎn)的上一個(gè)結(jié)點(diǎn)// 此時(shí) slow 指針指向中間結(jié)點(diǎn),分為在 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;} };

獲取更多精彩,請(qǐng)關(guān)注「seniusen」!

總結(jié)

以上是生活随笔為你收集整理的LeetCode 61——旋转链表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。