@Author:Runsen
@Date:2020/6/19
人生最重要的不是所站的位置,而是內心所朝的方向。只要我在每篇博文中寫得自己體會,修煉身心;在每天的不斷重複學習中,耐住寂寞,練就真功,不畏艱難,奮勇前行,不忘初心,砥礪前行,人生定會有所收穫,不留遺憾 (作者:Runsen )
作者介紹:Runsen目前大三下學期,專業化學工程與工藝,大學沉迷日語,Python, Java和一系列數據分析軟件。導致翹課嚴重,專業排名中下。.在大學60%的時間,都在CSDN。決定今天比昨天要更加努力。
前面文章,點擊下面鏈接
今日,我決定繼續更新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種法就是常規思路,直接將所有的元素取出,然後排個序,再重組就達到了目的。
遍歷所有鏈表,將所有節點的值放到一個數組中。將這個數組排序,然後遍歷所有元素得到正確順序的值。用遍歷得到的值,創建一個新的有序鏈表。
時間複雜度: ,其中 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
時間複雜度:,這裏 N 是這 k 個鏈表的結點總數,每一次從一個優先隊列中選出一個最小結點的時間複雜度是 ,故時間複雜度爲 。
空間複雜度:,使用優先隊列需要 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)
題目要求用 空間複雜度
這道題考的是快慢指針 空間複雜度
通過使用具有 不同速度 的快、慢兩個指針遍歷鏈表,空間複雜度可以被降低至。慢指針每次移動一步,而快指針每次移動兩步。
如果列表中不存在環,最終快指針將會最先到達尾部,此時我們可以返回 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