【LeetCode】25.K個一組翻轉(zhuǎn)鏈表

題目描述

25.K個一組翻轉(zhuǎn)鏈表

給你一個鏈表,每 k 個節(jié)點一組進(jìn)行翻轉(zhuǎn),請你返回翻轉(zhuǎn)后的鏈表码耐。

k是一個正整數(shù),它的值小于或等于鏈表的長度溶其。

如果節(jié)點總數(shù)不是k的整數(shù)倍骚腥,那么請將最后剩余的節(jié)點保持原有順序。

說明:你的算法只能使用常數(shù)的額外空間瓶逃。
你不能只是單純的改變節(jié)點內(nèi)部的值束铭,而是需要實際進(jìn)行節(jié)點交換。

示例:
給你這個鏈表:1->2->3->4->5
當(dāng)k= 2 時厢绝,應(yīng)當(dāng)返回: 2->1->4->3->5
當(dāng)k= 3 時契沫,應(yīng)當(dāng)返回: 3->2->1->4->5

題目解析

方法一:迭代法

解題思路

這個在上一題兩兩交換鏈表節(jié)點的基礎(chǔ)增加了難度怎披,需要K個一組進(jìn)行翻轉(zhuǎn)积担。首先我們可以將鏈表分為 “已翻轉(zhuǎn)”、“待翻轉(zhuǎn)”宫仗、“未翻轉(zhuǎn)” 三部分。在每次進(jìn)行翻轉(zhuǎn)前钞速,通過K值確定翻轉(zhuǎn)鏈表的范圍贷掖。

在上面一題已經(jīng)提到進(jìn)行鏈表翻轉(zhuǎn)時需要注意鏈表當(dāng)前遍歷節(jié)點嫡秕、其前驅(qū)節(jié)點和后繼節(jié)點渴语,需要額外的指針進(jìn)行標(biāo)識,防止鏈表翻轉(zhuǎn)后無法繼續(xù)向后遍歷昆咽。在這里我們 prev 指針代表待翻轉(zhuǎn)鏈表的前驅(qū)節(jié)點驾凶, end 指針代表待翻轉(zhuǎn)鏈表的末尾, next 指針代表待翻轉(zhuǎn)鏈表的后繼節(jié)點掷酗。

代碼示例

Java:

/**
 * Definition for singly-linked list.
 */
public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { 
        val = x;
    }
}

public ListNode reverseKGroup(ListNode head, int k) {
    if (head == null || head.next == null || k == 0) {
        return head;
    }
    
    // 哨兵節(jié)點
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    
    // 待翻轉(zhuǎn)鏈表的前驅(qū)節(jié)點
    ListNode prev = dummy;
    // 待翻轉(zhuǎn)鏈表的結(jié)束位置
    ListNode end = dummy;
    
    while(end.next != null) {
        for (int i = 0; i < k && end != null; i++) {
            end = end.next;
        }
        if (end == null) break;

        // 待翻轉(zhuǎn)鏈表的起始位置
        ListNode start = prev.next;
        // 待翻轉(zhuǎn)鏈表的后繼節(jié)點
        ListNode next = end.next;

        // 將待翻轉(zhuǎn)鏈表的next指針置為null调违,然后翻轉(zhuǎn)鏈表
        end.next = null;
        prev.next = reverse(start);
        start.next = next;
        
        // 前驅(qū)指針和結(jié)束指針移動
        prev = start;
        end = prev;
    }
    return dummy.next;
}

// 鏈表反轉(zhuǎn)
private ListNode reverse(ListNode head) {
    ListNode pre = null;
    ListNode curr = head;
    while (curr != null) {
        ListNode next = curr.next;
        curr.next = pre;
        pre = curr;
        curr = next;
    }
    return pre;
}

復(fù)雜度分析

時間復(fù)雜度:O(n*k)

空間復(fù)雜度:O(1)

方法二:遞歸法

解題思路

遞歸的思路主要在于將子問題傳遞到下一層遞歸函數(shù)處理,遞歸函數(shù)返回的即正確結(jié)果泻轰,當(dāng)前層只需要處理當(dāng)前層邏輯即可技肩。

當(dāng)前層只需要處理K個鏈表元素的翻轉(zhuǎn),并調(diào)用遞歸函數(shù)處理后面未翻轉(zhuǎn)的鏈表浮声,遞歸函數(shù)處理完未翻轉(zhuǎn)鏈表后返回結(jié)果虚婿,當(dāng)前層拿到結(jié)果后與自身翻轉(zhuǎn)結(jié)束后的鏈表進(jìn)行拼接,最后得到完整的翻轉(zhuǎn)結(jié)果泳挥。

代碼示例

Java:

/**
 * Definition for singly-linked list.
 */
public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { 
        val = x;
    }
}

public ListNode reverseKGroup(ListNode head, int k) {
    // terminator
    if (head == null || head.next == null || k == 0) {
        return head;
    }
    
    ListNode start = head , end = head;
    for (int i = 0; i < k; i++) {
        if (end == null) return head;
        end = end.next;
    }
    
    // process data: reverse linked list
    ListNode newHead = reverse(start, end);
    
    // recursion
    start.next = reverseKGroup(end, k);
    return newHead;
}

private ListNode reverse(ListNode start, ListNode end) {
    ListNode pre = null, curr = start, next = start;
    while (curr != end) {
        next = curr.next;
        curr.next = pre;
        pre = curr;
        curr = next;
    }
    return pre;
}

復(fù)雜度分析

時間復(fù)雜度:O(n*k)

空間復(fù)雜度:O(n)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末然痊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屉符,更是在濱河造成了極大的恐慌剧浸,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矗钟,死亡現(xiàn)場離奇詭異唆香,居然都是意外死亡,警方通過查閱死者的電腦和手機吨艇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門袋马,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秸应,你說我怎么就攤上這事虑凛。” “怎么了软啼?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵桑谍,是天一觀的道長。 經(jīng)常有香客問我祸挪,道長锣披,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮雹仿,結(jié)果婚禮上增热,老公的妹妹穿的比我還像新娘。我一直安慰自己胧辽,他們只是感情好峻仇,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著邑商,像睡著了一般摄咆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上人断,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天吭从,我揣著相機與錄音,去河邊找鬼恶迈。 笑死涩金,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暇仲。 我是一名探鬼主播步做,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼熔吗!你這毒婦竟也來了辆床?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤桅狠,失蹤者是張志新(化名)和其女友劉穎讼载,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體中跌,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡咨堤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了漩符。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片一喘。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嗜暴,靈堂內(nèi)的尸體忽然破棺而出凸克,到底是詐尸還是另有隱情,我是刑警寧澤闷沥,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布萎战,位于F島的核電站,受9級特大地震影響舆逃,放射性物質(zhì)發(fā)生泄漏蚂维。R本人自食惡果不足惜戳粒,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望虫啥。 院中可真熱鬧蔚约,春花似錦、人聲如沸涂籽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽又活。三九已至苔咪,卻和暖如春锰悼,著一層夾襖步出監(jiān)牢的瞬間柳骄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工箕般, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留耐薯,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓丝里,卻偏偏與公主長得像曲初,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子杯聚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容