leetcode初級演算法——連結串列
(題目源自leetcode,方法都是自(cai)己(ji)寫的,可能比較符合菜雞們的思路)
連結串列是做到現在,感覺自己最拉垮的一節,資料結構真的都還給老師了
1.刪除連結串列中的節點
請編寫一個函式,使其可以刪除某個連結串列中給定的(非末尾)節點。傳入函式的唯一引數為 要被刪除的節點 。
示例 1:
輸入:head = [4,5,1,9], node = 5
輸出:[4,1,9]
解釋:給定你連結串列中值為 5 的第二個節點,那麼在呼叫了你的函式之後,該連結串列應變為 4 -> 1 -> 9.
class Solution :
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
node.val = node.next.val
node.next = node.next.next
一開始沒看到啥意思,後來發現,給的node,就是讓你刪除的node。。。
2.刪除連結串列的倒數第N個節點
給定一個連結串列,刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。
示例:
給定一個連結串列: 1->2->3->4->5, 和 n = 2.
當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
len = 0
mid = head
if head.next == None:
return head.next
while mid != None:
mid = mid.next
len = len + 1
target = len - n
mid = head
while target > 1:
mid = mid.next
target = target - 1
if mid.next != None and target != 0:
mid.next = mid.next.next
if target == 0:
head = head.next
return head
比較蠢的辦法,用了兩次遍歷,第一次算出連結串列的總長度,第二次,根據n求出正方向遍歷的節點位置,刪掉。
也可以用快慢指標,快指標提前出發n步
或者用迭代回溯,回溯n次
(感覺連結串列相關的,很多都需要迭代回溯)
3.反轉連結串列
反轉一個單鏈表。
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head == None or head.next == None:
return head
out = self.reverseList(head.next)
head.next.next = head
head.next = None
return out
使用迭代回溯,這裡注意,其實out自始至終都沒有變過,就是指在了最後一個node,變得是head.next.next = head,而且head.next一定得擦除,不然會無限迴圈
4.合併兩個有序連結串列
將兩個升序連結串列合併為一個新的 升序 連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if not l1: return l2
if not l2: return l1
if l1.val<=l2.val:
l1.next = self.mergeTwoLists(l1.next,l2)
return l1
else:
l2.next = self.mergeTwoLists(l1,l2.next)
return l2
明明很簡單,自己想了好久。還是用遞迴,自己在連結串列的遞迴方面真的太不熟練了
5.迴文連結串列
請判斷一個連結串列是否為迴文連結串列。
示例 1:
輸入: 1->2
輸出: false
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
out = []
while head:
out.append(head.val)
head = head.next
return True if out[:]==out[::-1] else False
就是遍歷了連結串列,把所有的值放進了列表裡,然後判斷列表是否迴文。
6.環形連結串列
給定一個連結串列,判斷連結串列中是否有環。
如果連結串列中有某個節點,可以通過連續跟蹤 next 指標再次到達,則連結串列中存在環。 為了表示給定連結串列中的環,我們使用整數 pos 來表示連結串列尾連線到連結串列中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該連結串列中沒有環。注意:pos 不作為引數進行傳遞,僅僅是為了標識連結串列的實際情況。
如果連結串列中存在環,則返回 true 。 否則,返回 false 。
進階:
你能用 O(1)(即,常量)記憶體解決此問題嗎?
示例 1:
輸入:head = [3,2,0,-4], pos = 1
輸出:true
解釋:連結串列中有一個環,其尾部連線到第二個節點。
class Solution:
def hasCycle(self, head: ListNode) -> bool:
if not head:
return False
slow = head
quick = head.next
while slow != quick:
if not quick or not quick.next or not slow.next:
return False
slow = slow.next
quick = quick.next.next
return True
還是用了快慢指標,慢指標走一步,快指標走兩步,兩個指標指向同一個node,就證明有環。
還可以定義一個hash={},遍歷連結串列,把node放進hash表裡,遇到重複的,就證明是有環。