【LeetCode】反轉鏈表全家桶206 & 92 (Python)

206 

https://leetcode-cn.com/problems/reverse-linked-list/

反轉一個單鏈表。

示例:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
進階:
你可以迭代或遞歸地反轉鏈表。你能否用兩種方法解決這道題?

我們使用兩種方式解決這個問題:

  1. 迭代

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre = head
        ans = None
        while pre != None:
            nextTemp = pre.next
            pre.next = ans
            ans = pre
            pre = nextTemp
            
        return ans

思路:首先新建兩個變量pre和ans,然後遍歷鏈表,pre用來記錄當前遍歷的節點,ans作爲最後輸出的鏈表首先賦值變量None。每次遍歷鏈表的時候,將當前遍歷的節點指向ans,然後將該節點賦值給ans,pre記錄遍歷,最後輸出ans。

  1. 遞歸
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if head==None:
            return head
        if head.next == None:
            return head
        HEAD = self.reverseList(head.next)
        head.next.next = head # head爲當前節點的前一個節點,也就是讓當前節點指向上一個節點
        head.next = None #將當前節點的上一個節點指向None
        return HEAD

思路:看圖即可

92

https://leetcode-cn.com/problems/reverse-linked-list-ii/

反轉從位置 m 到 n 的鏈表。請使用一趟掃描完成反轉。

說明:
1 ≤ m ≤ n ≤ 鏈表長度。

示例:

輸入: 1->2->3->4->5->NULL, m = 2, n = 4
輸出: 1->4->3->2->5->NULL

解析

對於鏈表的問題,根據以往的經驗一般都是要建一個dummy node,連上原鏈表的頭結點,這樣的話就算頭結點變動了,我們還可以通過dummy->next來獲得新鏈表的頭結點。這道題的要求是隻通過一次遍歷完成,就拿題目中的例子來說,變換的是2,3,4這三個點,我們需要找到第一個開始變換結點的前一個結點,只要讓pre向後走m-1步即可,爲啥要減1呢,因爲題目中是從1開始計數的,這裏只走了1步,就是結點1,用pre指向它。萬一是結點1開始變換的怎麼辦,這就是我們爲啥要用dummy結點了,pre也可以指向dummy結點。然後就要開始交換了,由於一次只能交換兩個結點,所以我們按如下的交換順序:

1 -> 2 -> 3 -> 4 -> 5 -> NULL

1 -> 3 -> 2 -> 4 -> 5 -> NULL

1 -> 4 -> 3 -> 2 -> 5 -> NULL

我們可以看出來,總共需要n-m步即可,第一步是將結點3放到結點1的後面,第二步將結點4放到結點1的後面。這是很有規律的操作,那麼我們就說一個就行了,比如剛開始,pre指向結點1,cur指向結點2,然後我們建立一個臨時的結點t,指向結點3(注意我們用臨時變量保存某個結點就是爲了首先斷開該結點和前面結點之間的聯繫,這可以當作一個規律記下來),然後我們斷開結點2和結點3,將結點2的next連到結點4上,也就是 cur->next = t->next,再把結點3連到結點1的後面結點(即結點2)的前面,即 t->next = pre->next,最後再將原來的結點1和結點2的連接斷開,將結點1連到結點3,即 pre->next = t。這樣我們就完成了將結點3取出,加入結點1的後方。第二步將結點4取出,加入結點1的後方,也是同樣的操作。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
        dummy = ListNode(-1)
        dummy.next = head
        pre = dummy
        for i in range(m-1):
            pre = pre.next
            
        cur = pre.next
        for _ in range(m, n):
            t = cur.next
            cur.next = t.next
            t.next = pre.next
            pre.next = t

        return dummy.next

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章