K個節點翻轉連結串列

sodie2323發表於2024-10-21

概述

起因:leetcode題目 25. K 個一組翻轉連結串列

問題描述

給你連結串列的頭節點 head ,每 k 個節點一組進行翻轉,請你返回修改後的連結串列。

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

你不能只是單純的改變節點內部的值,而是需要實際進行節點交換。

示例一:

輸入:head = [1,2,3,4,5], k = 2
輸出:[2,1,4,3,5]

示例 2:

輸入:head = [1,2,3,4,5], k = 3
輸出:[3,2,1,4,5]

解決方法

我們需要構建一個函式,它會對連結串列進行K個節點翻轉。而不斷使用這個函式,就可以對每K個節點進行翻轉。

點選檢視程式碼
    struct Res{
        ListNode *head;
        bool flag;
        ListNode *tail;
    };

    Res reverse(ListNode* head,int k){
        ListNode newHead;
        ListNode *subHead,*subTail,*cur,*temp;
        //subHead 記錄反轉過程的頭節點
        //subTail 記錄反轉過程的尾節點
        //cur 要反轉的節點
        //temp 用於反轉的中間變數

        int cnt = 0; //記錄長度

        if(head){
            subHead = head;
            subTail = head;
            cur = head->next;
            cnt++;
        }

        while(cur && cnt<k){
            temp = cur;
            cur = cur->next;

            subTail->next = temp->next;
            temp->next = subHead;

            subHead = temp;
            cnt++;
        }
        bool flag = true;
        if(cnt<k) flag = false;
        return {subHead,flag,subTail};
    }

函式邏輯

  • 一開始翻轉連結串列的headtail都是正常連結串列的頭節點,cur則是要進行翻轉的節點

    • 我們把cur作為新的head,即舊的head會成為cur的下一個節點。
    • cnt 進行自增加一
  • 重複這個過程,直到cur為空。

  • 然後判斷 cntK 的關係:cnt < K 的話,則未能反轉 K 個節點。flagFalse

注意:這個過程中tail不需要變化,因為一開始的正常連結串列頭節點就是翻轉後的尾節點。

其中,函式返回翻轉後的頭節點和尾節點。特別地,flag是判斷是否翻轉了K個數。

實現不滿足K個節點則不翻轉

當不滿足K個節點時,函式返回的 res 中的flag屬性會為False
這時對這個翻轉後的連結串列再次進行翻轉的話,就可以實現不翻轉。

主函式實現

ListNode* reverseKGroup(ListNode* head, int k) {
    ListNode *newHead,*subTail;
    
    //首先進行一次翻轉,並初始newHead和subTail
    
    auto res = reverse(head,k);
    newHead = res.head;     
    subTail = res.tail;
    
    //如果第一次翻轉就不滿足K個節點,再次進行翻轉,並返回新的newHead
    if(res.flag == false){
        res = reverse(newHead,k);
        newHead = res.head;
        subTail = res.tail;
        return newHead;
    }          
  
    //對每K個節點進行翻轉
    while(1){
        auto res = reverse(subTail->next,k);        
      
        //不滿足K個節點,再次翻轉,並直接返回結果。
        if(res.flag == false){
            res = reverse(res.head,k);
            return newHead;
        }
        
        // 對subTail進行更新:連結翻轉後的子連結串列,並把subTail更新為子連結串列的tail。
        subTail->next = res.head;
        subTail = res.tail;
        cout<<subTail->val<<endl;
    }

    return newHead;
}

相關文章