七10、反轉和合並鏈表、 鏈表有環的判斷


「@Author:Runsen」node

編程的本質來源於算法,而算法的本質來源於數學,編程只不過將數學題進行代碼化。「---- Runsen」git

最近在從新梳理學算法的知識,本文爲鏈表常見操做複習的總結文章,會講解常見的鏈表題目實現思路及附上答案,這些題目在leetcode上對應的題號也有給出,好好學習算法吧~github

  • 單鏈表反轉
  • 鏈表中環的檢測
  • 兩個有序的鏈表合併
  • K個有序的鏈表合併

leetcode 對應題號:206,141,21,23web

LeetCode 第 206 題:反轉鏈表

反轉一個單鏈表。面試

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

題目不難,定義三個變量pre、cur、cur.next,分別記錄上一個結點,當前結點、下一個結點。算法

反轉一個單鏈表須要當前節點的next指針指向上一個結點pre,當前節點的指針指向下一個結點,上一個結點的指針指向當前節點。編程

經過迭代,依次反轉結點指向。具體代碼以下小程序

class Solution:
    def reverseList(self, head):
        cur, prev = head, None
        while cur:
            cur.next, prev, cur = prev, cur, cur.next
        return prev

LeetCode 第 141 題:判斷鏈表中是否有環

遍歷整個數組, 給出的數據包含在集合中則說明有環, 返回 True; 若遍歷完畢, 則說明無環, 返回 False,若是用列表也是同樣。數組

「暴力解法」微信

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        """
        暴力法:經過遍歷鏈表,用set來存儲訪問的節點,若是在set出現同樣的節點,說明有壞,時間複雜度O(n)
        :type head: ListNode
        :rtype: bool
        """

        st = set()
        while head:
            if head in st:
                return True
            st.add(head)
            head = head.next
        return False


      # 下面是列表
        l = []
        while head:
            if head in l:
                return True
            else:
                l.append(head)
                head = head.next
        return False   

從頭遍歷到尾,發現指向null,說明沒環。這明顯不靠譜。暴力的時間空間複雜度都是O(n)

題目要求用 空間複雜度。其實,這道題考的是「快慢指針」 空間複雜度

經過使用具備 不一樣速度 的快、慢兩個指針遍歷鏈表,空間複雜度能夠被下降至 。慢指針每次移動一步,而快指針每次移動兩步。

若是列表中不存在環,最終快指針將會最早到達尾部,此時咱們能夠返回 false。

能夠想象這樣一個場景, 你和一個朋友一塊兒散步, 你每次移動兩步, 朋友每次一步, 如爲單向定長道路, 你必然先到達重點. 如果環繞操場,則大家終將相遇.

class Solution(object):
    def hasCycle(self, head):
        slow = fast = head
        while slow and fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                return True
        return False

LeetCode  第21題:合併兩個有序鏈表

將兩個升序鏈表合併爲一個新的 升序 鏈表並返回。新鏈表是經過拼接給定的兩個鏈表的全部節點組成的。

示例: 

輸入:1->2->41->3->4
輸出:1->1->2->3->4->4

從兩鏈表第一個結點開始比較結點的值,取較小者做爲合併鏈表的元素,依次進行;後面若是有一個鏈表爲空,則直接把不爲空的鏈表接到合併鏈表的後面。

這個解決的方法使用遞歸,若是L1爲空就返回L2,L2爲空返回L1,L1的val<=L2的val,那麼繼續遞歸。

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


class Solution(object):
 def mergeTwoLists(self, l1, l2):
  """
  :type l1: ListNode
  :type l2: ListNode
  :rtype: ListNode
  """

  #遞歸的結束點就是L1或者L2爲空就返回
  #若是L1爲空就返回L2,L2爲空返回L1
  # if not (l1 and l2):
   # return l1 if l1 else l2
  if not l1:
            return l2
        elif not l2:
            return l1
  #L1的val<=L2的val,那麼繼續遞歸
  #當前L1的next指向一個遞歸函數
  #意思是L1的下一個和L2哪一個大,就做爲當前L1的next
   elif l1.val<=l2.val:
   l1.next = self.mergeTwoLists(l1.next,l2)
   return l1
  else:
   l2.next = self.mergeTwoLists(l1,l2.next)
   return l2

遞歸的代碼看起來是十分簡潔的

LeetCode 第 23 題:合併 k 個排序鏈表

合併 k 個排序鏈表,返回合併後的排序鏈表。請分析和描述算法的複雜度。

示例: 
輸入:
[
 1->4->5,
 1->3->4,
 2->6
]
輸出: 1->1->2->3->4->4->5->6 

第一種法就是常規暴力思路,直接將全部的元素取出,而後排個序,再重組就達到了目的。

遍歷全部鏈表,將全部節點的值放到一個數組中。將這個數組排序,而後遍歷全部元素獲得正確順序的值。用遍歷獲得的值,建立一個新的有序鏈表。

時間複雜度: ,其中 N 是節點的總數目

空間複雜度:

排序花費 空間(這取決於你選擇的算法)。建立一個新的鏈表花費 的空間。

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


class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode :
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """

        self.nodes = []
        head = point = ListNode(0)
        for l in lists:
            while l:
                self.nodes.append(l.val)
                l = l.next
        for x in sorted(self.nodes):
            point.next = ListNode(x)
            point = point.next
        return head.next

「人生最重要的不是所站的位置,而是心裏所朝的方向。只要我在每篇博文中寫得本身體會,修煉身心;在天天的不斷重複學習中,耐住寂寞,練就真功,不畏艱難,奮勇前行,不忘初心,砥礪前行,人生定會有所收穫,不留遺憾 (做者:Runsen )」

本文已收錄 GitHub,傳送門~[1] ,裏面更有大廠面試完整考點,歡迎 Star。



Reference

[1]

傳送門~: https://github.com/MaoliRUNsen/runsenlearnpy100


更多的文章

點擊下面小程序



- END -

本文分享自微信公衆號 - Python之王(sen13717378202)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索