題目描述
題目分析
很容易發現,如果k是n的整數倍,相當于沒有移動。這樣直接對k%n使得k在一個可以接受的范圍。
因為是順序移動,各元素之間的相對位置保持不變,所以就想著將鏈表先變成一個環。然后再移動頭指針,最后再斷開。
頭指針我們只能向后(右)移動,但是頭指針的向右移動相當于整個鏈表向左移動,因此我們要將頭指針移動n-k次,這樣和向右移動k次鏈表的效果相同。
得到頭指針后我們再將鏈表斷開。我這里用了一種比較笨的方法,是在頭指針的基礎上再移動鏈表的長度,看題解才發現,原來尾指針就在頭指針的前面,我只要保存尾指針,移動次數為n-k-1
。馬達馬達打內
AC代碼
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* rotateRight(ListNode* head, int k) {if (head == nullptr || head->next == nullptr) return head;int n = 1;ListNode *p = head;while (p->next != nullptr) {++n;p = p->next;}k %= n;if (k == 0) return head;k = n - k;p->next = head;while (k--) {head = head->next;}p = head;--n;while (n--) {p = p->next;}p->next = nullptr;return head;}
};
需要注意的是,在遍歷鏈表的時候,是使得指針指向當前節點還是指向當前節點的前一個節點是有講究的,單純的遍歷的話可能不需要考慮,但是我們要獲得尾指針來形成環,則必須保存的是當前節點的前一個節點。
這些細節能夠顯示代碼的能力,如果思考的不夠深入就會犯錯。
題解代碼
class Solution {
public:ListNode* rotateRight(ListNode* head, int k) {if (k == 0 || head == nullptr || head->next == nullptr) {return head;}int n = 1;ListNode* iter = head;while (iter->next != nullptr) {iter = iter->next;n++;}int add = n - k % n;if (add == n) {return head;}iter->next = head;while (add--) {iter = iter->next;}ListNode* ret = iter->next;iter->next = nullptr;return ret;}
};