1. 程式人生 > >[leetcode-連結串列]25. k個一組翻轉連結串列

[leetcode-連結串列]25. k個一組翻轉連結串列

給出一個連結串列,每 個節點一組進行翻轉,並返回翻轉後的連結串列。

是一個正整數,它的值小於或等於連結串列的長度。如果節點總數不是 的整數倍,那麼將最後剩餘節點保持原有順序。

示例 :

給定這個連結串列:1->2->3->4->5

當 = 2 時,應當返回: 2->1->4->3->5

當 = 3 時,應當返回: 3->2->1->4->5

說明 :

  • 你的演算法只能使用常數的額外空間。
  • 你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。

//=======================================================================

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseKGroup(struct ListNode* head, int k) {
    //處理特殊條件
    if(head == NULL || head->next == NULL || k<=1)
    {
        return head;
    }
    
    //先找到第一組,包含k個元素,newHead指向第一組後面的第一個結點
    struct ListNode *newHead = head;
    int count=0;
    while(newHead && count < k)
    {
        newHead = newHead->next;
        count += 1;
    }    
    
    //    1,     2,     3,        4,       5   k=2
    //  head           newHead             newHead
    //           temp
    //    ---------------->
    // newHead
    //           head
    //                  temp
    //     
    
    //如果第一組可以找全,則進行翻轉; 反之,不需要翻轉
    if(count == k)
    {
        //同理,處理後續元素的k組翻轉,最後返回翻轉後的頭結點newHead
        newHead = reverseKGroup(newHead, k);
        
        //對前面k個元素進行翻轉
        struct ListNode *temp=NULL;
        while(count > 0)
        {
            temp = head->next; //備份第二個結點
            
            head->next = newHead; //兩組銜接過渡 ,第一個的下一個結點為下一組翻轉後的頭結點 
            
            newHead = head;  //此時的第一個為合併資料後的部分的第一個 
            
            head = temp; //第二個為新的頭 
            
            count -= 1;
        }
        
        head = newHead;
    }
    
    return head;
}

//=======================================================================

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *reverseList(struct ListNode *head, int k)
{
    struct ListNode *pnext=head;
    while(pnext && k>0) //找到k個元素的下一個元素
    {
        pnext=pnext->next;
        k--;
    }
    
    if(k>0) //不到k個元素,則無需翻轉
        return head;
    
    struct ListNode *nexthead=pnext, *pcur=head, *temp=NULL; 
    while(pcur != pnext) //前面k個元素以此翻轉
    {
        temp=pcur->next;
        pcur->next = nexthead;
        nexthead=pcur;
        pcur=temp;
    }
    
    return nexthead;
}

struct ListNode* reverseKGroup(struct ListNode* head, int k) {
    if(head==NULL || head->next==NULL || k<=1)
    {
        return head;
    }
    
    struct ListNode dummy={.next=head}; //設定dummy首結點
    struct ListNode *pcur=&dummy;
    
    while(pcur) //從前往後以此翻轉k個元素
    {
        pcur->next = reverseList(pcur->next, k); //翻轉前k個元素
        for(int i=0; pcur && i<k; ++i) //前進k個元素
        {
            pcur=pcur->next;
        }
    }
    
    return dummy.next;
}