2. 解題思路
- 對於鏈表涉及到反轉、倒置等操做,通常都須要兩個指針:prev、cur
- 根據翻轉的規則,當翻轉次數恰好是鏈表長度list_len的整數倍時,實際上翻轉後的鏈表和未翻轉的原鏈表是同樣的
- 翻轉次數k >= 0,因爲k的大小不肯定,當k是list_len的整數倍時,直接返回(由於經過k次翻轉後,仍是和原鏈表同樣);不然,實際須要翻轉的次數times是:(k % list_len)
- 所以,prev指向第(list_len - times)個節點,cur指向第(list_len - times + 1)個節點
- 採用頭插法將cur指向的鏈表插入到原鏈表的頭部
3. 算法
- 統計鏈表長度爲list_len
- 判斷k是否是list_len的整數倍
- 肯定prev指針的位置,也就是第(list_len - times)個節點
- 肯定cur指針的位置,也就是prev->next指向的節點
- 找到原鏈表的尾節點tail
- 採用頭插法進行翻轉
4. 實現
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) return head;
int list_len = 0;
for(ListNode *tmp = head; tmp != NULL; tmp = tmp->next){
list_len++;
}
if(k % list_len == 0) return head;
int end = list_len - (k % list_len);
ListNode *prev = head;
for(int i = 1; i < end; i++){
prev = prev->next;
}
ListNode *cur = prev->next;
ListNode *tail = cur;
while(tail != NULL && tail->next != NULL){
tail = tail->next;
}
prev->next = tail->next;
tail->next = head;
return cur;
}
};
//tricky solution
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(head == NULL) return head;
int list_len = 1;
ListNode *tail = head;
for(; tail->next != NULL; tail = tail->next){
list_len++;
}
if(k % list_len == 0) return head;
int end = list_len - (k % list_len);
ListNode *prev = head;
for(int i = 1; i < end; i++){
prev = prev->next;
}
ListNode *cur = prev->next;
tail->next = head; //tricky: 首尾相連,構成環
prev->next = NULL; //prev也就是翻轉後鏈表的尾節點,所以今後處將環打開
return cur;
}
};