[LeetCode] 61. Rotate List

1. 原題連接:https://leetcode.com/problems/rotate-list/

2. 解題思路

  1. 對於鏈表涉及到反轉、倒置等操做,通常都須要兩個指針:prev、cur
  2. 根據翻轉的規則,當翻轉次數恰好是鏈表長度list_len的整數倍時,實際上翻轉後的鏈表和未翻轉的原鏈表是同樣的
  3. 翻轉次數k >= 0,因爲k的大小不肯定,當k是list_len的整數倍時,直接返回(由於經過k次翻轉後,仍是和原鏈表同樣);不然,實際須要翻轉的次數times是:(k % list_len)
  4. 所以,prev指向第(list_len - times)個節點,cur指向第(list_len - times + 1)個節點
  5. 採用頭插法將cur指向的鏈表插入到原鏈表的頭部

3. 算法

  1. 統計鏈表長度爲list_len
  2. 判斷k是否是list_len的整數倍
  3. 肯定prev指針的位置,也就是第(list_len - times)個節點
  4. 肯定cur指針的位置,也就是prev->next指向的節點
  5. 找到原鏈表的尾節點tail
  6. 採用頭插法進行翻轉

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;
    }
};
相關文章
相關標籤/搜索