LeetCode 25.k個一組翻轉鏈表(Reverse Nodes in k-Group)

LeetCode.jpg

目錄鏈接:http://www.lxweimin.com/p/9c0ada9e0ede

k個一組翻轉鏈表

給出一個鏈表,每 k 個節點一組進行翻轉,并返回翻轉后的鏈表。

k 是一個正整數,它的值小于或等于鏈表的長度。如果節點總數不是 k 的整數倍,那么將最后剩余節點保持原有順序。

示例 :

給定這個鏈表:1->2->3->4->5

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

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

說明 :

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

切題

一、Clarification

1、每組k個元素翻轉后,每組之間的銜接。[1,k] 與 [k+1,2k]之間銜接

2、注意 剩余元素的處理

二、Possible Solution

1、迭代

遍歷鏈表 找出每組的 首尾以及下一組的首,借助單鏈表翻轉獲得翻轉后的首尾,對首尾節點銜接處理,對哨兵節點移位處理

時間復雜度 O(N)

2、遞歸

遞歸終止條件:

剩余節點 < k

遞歸從里向外出來,每層遞歸返回當前層級鏈表翻轉后的頭節點,那么每層遞歸中我們知道當前層級翻轉后的頭尾節點以及下一個k元素組的頭節點(遞歸的上一層級),可以很輕松地將翻轉后的鏈表銜接起來

3、借助棧

將k個元素壓入棧,通過出棧翻轉,注意剩余元素處理

Python3實現

迭代 借助單鏈表翻轉

# @author:leacoder
# @des: 迭代 借助單鏈表翻轉  k個一組翻轉鏈表
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        cur = head #由于遍歷
        dim = ListNode(0) #新建一節點 
        dim.next = head #next指向head
        pre = dim #pre 賦值為 dim  1、記錄和獲取 k個一組的頭 2、方便統一處理
        # pre 與 dim 均為哨兵
        count = 1
        while cur: #遍歷鏈表
            if count % k == 0: #k個一組 對這里面的數據翻轉
                nextstart = cur.next #記錄 后一個 k個一組的 頭節點
                cur.next = None #賦值為None 前面 k個一組數據 為新的鏈表 以 None結束 這個新鏈表可以采用206的處理方式
                end, start = self.reverse(pre.next)  #翻轉新鏈表 返回翻轉的  尾 和 頭  注pre.next 為新鏈表翻轉前的頭
                # 銜接處理,哨兵的next指向翻轉后的頭, 翻轉后的尾的next指向nextstart
                # pre 和 cur 依次下移k個元素 變為 end 和 nextstart下一輪處理就變成本輪一樣了
                pre.next,end.next,pre,cur = start,nextstart,end,nextstart
            else:
                cur = cur.next #我們關心k個一組的首尾
            count += 1
        return dim.next
    
    def reverse(self, head): #翻轉鏈表
        dim1,cur,pre = head,head,None
        while cur: #遍歷
            cur.next,pre,cur  = pre,cur,cur.next
        return dim1,pre    #翻轉后end 和 start

遞歸

# @author:leacoder
# @des: 遞歸  k個一組翻轉鏈表
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
       
        if self.isEnd(head,k):
            return head
        pre = ListNode(None) # 哨兵
        pre.next,cur,count =  head,head,1  

        while count <= k: # 翻轉 k個元素鏈表  處理類似 206
            cur.next,pre,cur,count  = pre,cur,cur.next,count + 1 
        # 循環結束后 cur 指向 下一組 k個元素(未翻轉)的頭 ;pre指向當前組在翻轉后的頭節點
        nexthead = self.reverseKGroup(cur,k) # nexthead 下一組翻轉后的頭節點

        head.next = nexthead #當前組的head在翻轉后成為尾節點,其next指向nexthead 下一組翻轉后的頭節點
        return pre  # 返回 翻轉后的頭節點

    # 遞歸終止判斷:
    def isEnd(self,head,k):
        count,cur = 0,head
        while cur:
            count = count + 1
            cur = cur.next
            if count >= k:
                return False # 
        return True

借助棧


# @author:leacoder
# @des: 借助棧  k個一組翻轉鏈表
class Solution:
    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        result= ListNode(None)
        cur,result.next = head,head
        tmpresult = result
        stack = [] # 列表實現棧的 先入后出功能
        count = 0

        while cur:
            count = count + 1
            stack.append(cur) # 入棧
            cur = cur.next
            if count % k == 0: # 已存儲k個元素
                count = 0
                while stack: # 出棧倒換
                    tmpresult.next = stack.pop()
                    tmpresult = tmpresult.next

        # 處理 stack 中剩余元素
        while stack:
            tmpresult.next = stack.pop(0) # 
            tmpresult = tmpresult.next 
        return result.next

C++實現

存儲法

用數組存儲k個元素,雖然能通過但是執行用時有點長,不過邏輯簡單

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 * @author:leacoder
 * @des: 存儲法 k個一組翻轉鏈表
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode *nodearray[k];//存儲 需翻轉的 k個節點
        ListNode* result = new ListNode(0); //翻轉后鏈表 用于結果返回
        ListNode* ret = result;//由于存儲翻轉后鏈表
        int count = 0;
        while( NULL != head){
            ListNode* next = head->next; //記錄下移節點
            nodearray[count] = head; //記錄到數組
            count++;//數組 下標自加 
            if(k == count){ //已存 k個值  需要翻轉了
               for(int i = k;i>0;i--){ //循環讀取 數組中數據
                   ret->next = nodearray[i-1]; //從后往前去數組中數據 添加到ret鏈表中
                   ret = ret->next;//移位
                   nodearray[i-1] = NULL;//置空
                   count--;//數組中數據個數--
               }
            }
            head = next;
        }
        
        for(int i = 0;i<count;i++){//處理不需要翻轉的數據
           ret->next = nodearray[i];
           ret = ret->next;
           nodearray[i] = NULL;
        }
        ret->next = NULL;
        return result->next;
    }
};

k作為函數參數傳入后就確定了可以當做常數,但是k作為參數可以為合理范圍內任意值不確定,這點和題目描述說明貌似有點出入
說明 : 你的算法只能使用常數的額外空間。
你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。

我這種方法處理也只是提供一種思路,待后續其他實現方法


GitHub鏈接:
https://github.com/lichangke/LeetCode

知乎個人首頁:
https://www.zhihu.com/people/lichangke/

簡書個人首頁:
http://www.lxweimin.com/u/3e95c7555dc7

個人Blog:
https://lichangke.github.io/

歡迎大家來一起交流學習

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容