leetcode筆記-連結串列
反轉連結串列
cur 記錄要處理的節點 pre 記錄cur前一個節點 實際上始終是初始狀態下的第一個節點 每次將cur.next更改為頭節點,並更新head
def reverseList(self, head):
if head == None or head.next == None:
return head
pre = head
cur = pre.next
while not cur == None:
pre.next = cur.next
cur.next = head
head = cur
cur = pre.next
return head
兩數相加
兩個連結串列有一樣長,或一長一短兩種情況 先處理一樣長的部分 如果連結串列L2未處理完,L1一定已處理完 再處理接下來的部分 當所有節點處理完後,可能出現進位的情況 最後判斷一次是否有進位
def addTwoNumbers(self, l1, l2):
e = 0
p = l1
q = l2
t = None
while p and q:
p.val = (p.val+q.val+e)
e = p.val//10
p.val = p.val%10
t = p
p = p.next
q = q.next
if q != None:
p = t
p.next = q
p = p.next
while p:
p.val = p.val+e
e = p.val//10
p.val = p.val%10
t = p
p = p.next
if e ==1 :
p = t
p.next = ListNode(1)
return l1
合併兩個有序連結串列
1.兩個連結串列均未處理完 2.其中一個連結串列未處理的部分節點
def mergeTwoLists(self, l1, l2):
cur = ListNode(0)
head = cur
while l1 and l2:
if l1.val < l2.val:
cur.next = l1
cur = cur.next
l1 = l1.next
else:
cur.next = l2
cur = cur.next
l2 = l2.next
if l1!=None:
cur.next=l1
if l2!=None:
cur.next=l2
return head.next
合併k個有序連結串列
一開始選擇和合並兩個有序連結串列一樣的思路,每次從k個鏈中選出最小節點。連結串列個數為m,節點總數為n,時間複雜度O(n*m) 只有兩個連結串列時,建立連結串列的過程即可對大小進行判斷,時間複雜度O(n) 對於多個連結串列可以先遍歷一遍然後排序,建立新連結串列。節點個數為n,三個階段時間複雜度分別為O(n),O(nlogn),O(n) 注意對節點陣列中空元素的處理
def mergeKLists(self, lists):
ret = []
if len(lists) == 0:
return None
for x in lists:
while x:
ret.append(x.val)
x = x.next
if len(ret)==0:
return None
ret.sort()
head = ListNode(ret[0])
cur = head
for n in ret[1:]:
cur.next = ListNode(n)
cur = cur.next
return head
旋轉連結串列
將連結串列成環,從新走過k-n個節點,修改頭節點位置,斷鏈 注意:1.空連結串列 2 k大於n時需要取餘 由於 k可能大於連結串列長度 所以至少要遍歷一次 求的連結串列長度n 共訪問2n-k次 也可以參考旋轉陣列,整個翻轉連結串列,然後反轉前k個節點,再反轉後k個節點 訪問2n次
def rotateRight(self, head, k):
if head == None:
return None
cur = head
n=1
while cur.next!=None:
n+=1
cur = cur.next
cur.next = head
k = k % n
n = n-k
while n>0:
cur = cur.next
n-=1
head = cur.next
cur.next = None
return head
環形連結串列
如果連結串列有環,當指標進入環後 就會無限迴圈 設定快慢指標 步長為1,2 變為一個追擊問題如果追得上 則有環。 如果出現一方到達終點(指標為空)則無環
def hasCycle(self, head):
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
環形連結串列 II
將連結串列分為無環部分m和有環部分n 快指標每次前進比滿指標多1,相遇時正好多n 則迴圈次數=環長度 相遇時,慢指標走過m和部分環c 快指標走過 m+n+c m+n+c = 2(m+c) 所以m+c部分正好等於環長度 所以m長度等於相遇點到環起點的長度
def detectCycle(self, head):
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
p = head
while p!=slow:
p = p.next
slow = slow.next
return p
return None
相交連結串列
兩個連結串列 a,b 分為獨有部分LA,LB和公共部分C 從a開始經過 LA-C-LB-C 從b開始經過 LB-C-LA-C 最終會同時到達C 找到第一個公共節點
def getIntersectionNode(self, headA, headB):
heada = headA
headb = headB
while heada!=headb:
heada = headB if heada == None else heada.next
headb = headA if headb == None else headb.next
return heada
刪除連結串列中的節點
def deleteNode(self, node):
node.val = node.next.val
node.next = node.next.next
node = node.next