206. 反轉(zhuǎn)鏈表(Python)

題目

難度:★★☆☆☆
類型:鏈表

反轉(zhuǎn)一個單鏈表胰丁。

進(jìn)階:
你可以迭代或遞歸地反轉(zhuǎn)鏈表凄鼻。你能否用兩種方法解決這道題腊瑟?

示例

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

解答

方案1:迭代

使用迭代法反轉(zhuǎn)鏈表需要三個臨時變量:

當(dāng)前結(jié)點(diǎn)cur:當(dāng)前要處理的鏈表結(jié)點(diǎn);

  1. 前一個結(jié)點(diǎn)prev:已經(jīng)處理好的新鏈表的頭結(jié)點(diǎn)块蚌;

  2. 臨時結(jié)點(diǎn)tmp:用于暫存cur的下一個鏈表結(jié)點(diǎn)闰非。

  3. 遍歷鏈表過程中,不斷進(jìn)行的重復(fù)便是cur.next=prev:

prev, cur->tmp ==> prev <- cur, tmp

每一輪循環(huán)匈子,因?yàn)橛腥齻€變量河胎,所以需要三句話分別更新,鏈表方向調(diào)頭工序夾在里面:

  1. 先把當(dāng)前結(jié)點(diǎn)cur的下一個結(jié)點(diǎn)賦給臨時結(jié)點(diǎn)tmp暫存虎敦;

  2. 將當(dāng)前結(jié)點(diǎn)的連接方向調(diào)頭游岳,連接prev,cur成為新鏈表的頭結(jié)點(diǎn)其徙;

  3. prev結(jié)點(diǎn)更新為新鏈表的頭結(jié)點(diǎn)胚迫;

  4. 將tmp中暫存的變量歸還cur結(jié)點(diǎn)。

class Solution(object):     # 迭代
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        cur, prev = head, None

        while cur:
            tmp = cur.next              # 臨時列表唾那,用于暫存結(jié)果
            cur.next = prev             # 更換連接方向
            prev = cur                  # 后移
            cur = tmp                   # 后移

        return prev

方案2:遞歸

假設(shè)鏈表為:

1 -> 2 -> 3-> ... -> k-1 -> k -> k+1 -> ... -> n -> None

并且我們已經(jīng)構(gòu)造了函數(shù)访锻,使得鏈表從k-1之后都被反轉(zhuǎn):

1 -> 2 -> 3-> ... ->k-1 -> k -> k+1 <- ... <- n

我們希望k-1的下一個結(jié)點(diǎn)指向k,則k.next.next=k:

1 -> 2 -> 3-> ... ->k-1 -> k <- k+1 <- ... <- n

需要注意的是,結(jié)點(diǎn)1的下一個結(jié)點(diǎn)是None期犬,需要特殊處理河哑,在之前操作的基礎(chǔ)上設(shè)置k的下一個結(jié)點(diǎn)為None:

n -> n-1 -> ... -> k+1 \
??????????-> k -> None
1-> 2-> 3 -> ... ->k-1 /

class Solution(object):     # 迭代
   def reverseList(self, head):
       """
       :type head: ListNode
       :rtype: ListNode
       """
       if not head or not head.next:       # 如果輸入結(jié)點(diǎn)是空,或只有一個結(jié)點(diǎn)龟虎,返回即可
           return head

       p = self.reverseList(head.next)     # 將下一個結(jié)點(diǎn)之后的部分逆序
       head.next.next = head               # 反轉(zhuǎn)當(dāng)前結(jié)點(diǎn)
       head.next = None                    # 設(shè)置當(dāng)前結(jié)點(diǎn)的下一個結(jié)點(diǎn)為None
       return p

這里璃谨,特地為大家做了一個腳本,近距離展示一下遞歸是如何工作的:

def create_linked_list(nums):
    """
    創(chuàng)建鏈表
    :param nums: 輸入代表里鏈表的數(shù)字列表
    :return: 返回創(chuàng)建好的鏈表的頭結(jié)點(diǎn)鲤妥,可以得到整個鏈表的所有信息
    """
    if not nums:                        # 輸入空列表
        return
    head = prev = ListNode(nums[0])     # 第一個結(jié)點(diǎn)
    for num in nums[1:]:
        tmp = ListNode(num)             # 創(chuàng)建當(dāng)前結(jié)點(diǎn)
        prev.next = tmp                 # 掛在已經(jīng)創(chuàng)建好的鏈表末尾
        prev = prev.next                # 指針后移
    return head


def print_linked_list(head):
    """
    打印鏈表
    :param head: 要打印的鏈表的頭結(jié)點(diǎn)
    :return: 結(jié)點(diǎn)值列表
    """
    nums = []
    while head:
        nums.append(head.val)
        head = head.next
    print(nums)
    return nums


class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None


class Solution(object):   
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next:       # 如果輸入結(jié)點(diǎn)是空佳吞,或只有一個結(jié)點(diǎn),返回即可
            return head

        p = self.reverseList(head.next)     # 將下一個結(jié)點(diǎn)之后的部分逆序
        head.next.next = head               # 反轉(zhuǎn)當(dāng)前結(jié)點(diǎn)
        head.next = None                    # 設(shè)置當(dāng)前結(jié)點(diǎn)的下一個結(jié)點(diǎn)為None
        print_linked_list(p)                # 展示一下處理過程棉安,如果不需要的話可以注釋掉
        return p


if __name__ == "__main__":
    head = create_linked_list([1, 2, 3, 4, 5, 6, 7, 8, 9])
    s = Solution()
    reversed_head = s.reverseList(head)

該腳本的輸出為:

[9, 8]
[9, 8, 7]
[9, 8, 7, 6]
[9, 8, 7, 6, 5]
[9, 8, 7, 6, 5, 4]
[9, 8, 7, 6, 5, 4, 3]
[9, 8, 7, 6, 5, 4, 3, 2]
[9, 8, 7, 6, 5, 4, 3, 2, 1]

創(chuàng)建鏈表(create_linked_list)和打印鏈表(print_linked_list)函數(shù)源自【鏈表基礎(chǔ)】底扳。

如有疑問或建議,歡迎評論區(qū)留言~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贡耽,一起剝皮案震驚了整個濱河市衷模,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菇爪,老刑警劉巖算芯,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柒昏,死亡現(xiàn)場離奇詭異凳宙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)职祷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門氏涩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人有梆,你說我怎么就攤上這事是尖。” “怎么了泥耀?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵饺汹,是天一觀的道長。 經(jīng)常有香客問我痰催,道長兜辞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任夸溶,我火速辦了婚禮逸吵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缝裁。我一直安慰自己扫皱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著韩脑,像睡著了一般氢妈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上段多,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天允懂,我揣著相機(jī)與錄音,去河邊找鬼衩匣。 笑死蕾总,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的琅捏。 我是一名探鬼主播生百,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼柄延!你這毒婦竟也來了蚀浆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤搜吧,失蹤者是張志新(化名)和其女友劉穎市俊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滤奈,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摆昧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蜒程。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绅你。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖昭躺,靈堂內(nèi)的尸體忽然破棺而出忌锯,到底是詐尸還是另有隱情,我是刑警寧澤领炫,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布偶垮,位于F島的核電站,受9級特大地震影響帝洪,放射性物質(zhì)發(fā)生泄漏似舵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一碟狞、第九天 我趴在偏房一處隱蔽的房頂上張望啄枕。 院中可真熱鬧,春花似錦族沃、人聲如沸频祝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽常空。三九已至沽一,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間漓糙,已是汗流浹背铣缠。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昆禽,地道東北人蝗蛙。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像醉鳖,于是被迫代替她去往敵國和親捡硅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348