[Leetcode力扣 25] Reverse Nodes in k-Group

Niu Yutao發表於2020-10-20

一、題目描述

k個一組反轉連結串列。本題中連結串列至少有1個節點,k保證是有效的,即1<=k<=n。

二、解法一:使用reverseList函式

只考慮O(1)儲存空間的辦法的話,比較容易想到的就是,每數到k個節點就返回去反轉這k個節點。不能邊數邊反轉的原因是:不能確定後面還夠不夠k個節點,如果不夠k個節點的話是不用反轉的。

假設已經有了反轉k個節點的子函式,那麼整個過程就可以這樣處理:每k個一組的連結串列反轉以後,要得到反轉後的連結串列段的head和tail,設當前的head和tail分別為this_head和this_tail,然後把上一個tail連著這一個head,即last_tail->next = this_head,再更新tail值為this_tail,即last_tail = this_tail,這樣就能把整個連結串列都串起來了。

下面考慮reverseList的子函式應該怎麼寫,受反轉單連結串列那道題(LeetCode206)的啟發,那道題的遞迴解法就是找到了每一個子問題的tail和head,tail就是反轉前的第一個節點,迭代時可以很容易地得到,head就是子問題返回的節點,把這個思想稍作修改,就能得到這道題裡面的子函式。整體程式碼如下:

/**
 * 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* reverseKGroup(ListNode* head, int k) 
    {
        if(!head->next || 1 == k) return head;
        
        //初始化start,tail。為了tail的初始值,要申請一個新節點作為head之前的節點
        ListNode* p = head, *start = head;
        ListNode* pre = new ListNode(0);
        ListNode* tail = pre;            
        int cnt = 0;
        while(p)
        {
            ++cnt;
            ListNode* nex = p->next;

            //當找到k個節點後,反轉這k個節點,並將上一個tail連向這一個頭,然後更新tail和start
            if(cnt == k)
            {
                tail->next = reverse(start, k);
                tail = start;
                cnt = 0;
                start = nex;
            }
            p = nex;
        }
        if(cnt != 0) tail->next = start;    //後面可能還有不足k個的節點,要注意這部分的連線
        return pre->next;
    }
    
private:
    //反轉從start開始的k個節點,返回反轉後的頭節點指標
    ListNode* reverse(ListNode* start, int k)
    {
        //本題能保證start開始一定存在k個節點,所以該函式中不需要考慮邊界情況
        int cnt = 1;
        ListNode *p = start->next;
        start->next = nullptr;
        while(p)
        {
            ListNode* nex = p->next;
            p->next = start;
            start = p;
            p = nex;
            
            ++cnt;
            if(cnt == k) break;
        }
        return start;
    }
};

 

相關文章