六十九、Python | Leetcode鏈表系列(中篇)

@Author:Runsen
@Date:2020/6/19

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

作者介紹:Runsen目前大三下學期,專業化學工程與工藝,大學沉迷日語,Python, Java和一系列數據分析軟件。導致翹課嚴重,專業排名中下。.在大學60%的時間,都在CSDN。決定今天比昨天要更加努力。
前面文章,點擊下面鏈接

我的Python教程,不斷整理,反覆學習

今日,我決定繼續更新Python教程,今天就開始了六十八、Python | Leetcode鏈表系列(上篇)。

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

#將兩個升序鏈表合併爲一個新的 升序 鏈表並返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。 
# 示例: 
#
# 輸入:1->2->4, 1->3->4
#輸出:1->1->2->3->4->4
# 
# Related Topics 鏈表

這個解決的方法使用遞歸,如果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 
# Related Topics 堆 鏈表 分治算法

第1種法就是常規思路,直接將所有的元素取出,然後排個序,再重組就達到了目的。

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

時間複雜度:O(NlogN)O(N\log N) ,其中 N 是節點的總數目

空間複雜度:O(N)O(N)

排序花費O(N)O(N)空間(這取決於你選擇的算法)。
創建一個新的鏈表花費 O(N)O(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

時間複雜度:O(Nlogk)O(N \log k),這裏 N 是這 k 個鏈表的結點總數,每一次從一個優先隊列中選出一個最小結點的時間複雜度是 O(logk)O(logk),故時間複雜度爲 O(Nlogk)O(N \log k)
空間複雜度:O(k)O(k),使用優先隊列需要 k 個空間,“穿針引線”需要常數個空間,因此空間複雜度爲 O(k)O(k)

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

你能用 O(1)(即,常量)內存解決此問題嗎?

遍歷整個數組, 給出的數據包含在集合中則說明有環, 返回 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
        

暴力的時間空間複雜度都是O(n)

題目要求用 O(1)O(1)空間複雜度

這道題考的是快慢指針 O(1)O(1)空間複雜度

通過使用具有 不同速度 的快、慢兩個指針遍歷鏈表,空間複雜度可以被降低至O(1)O(1)。慢指針每次移動一步,而快指針每次移動兩步。

如果列表中不存在環,最終快指針將會最先到達尾部,此時我們可以返回 false。

進階的要求是以 O(1) 的空間複雜度實現, 想象這樣一個場景, 你和一個朋友一起散步, 你每次移動兩步, 朋友每次一步, 如爲單向定長道路, 你必然先到達重點. 若是環繞操場,則你們終將相遇.

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 第 206 題:反轉鏈表

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

將當前節點的next指針指向前驅的節點,需要有2個指針來記錄,一個記錄當前節點,一個記錄前驅節點,循環5次直到列表結束,三個簡單複製語句

class Solution:
    def reverseList(self, head):
        cur, prev = head, None
        while cur:
            cur.next, prev, cur = prev, cur, cur.next
        return prev
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章