程式碼隨想錄演算法訓練營第三天 | 203.移除連結串列元素 707.設計連結串列 206.反轉連結串列

Y荷兰豆Y發表於2024-06-07

python定義連結串列
val:資料域,節點儲存的元素。
next:指標域,指向下一個節點的指標,最後一個節點指向None表示空指標。

點選檢視程式碼
class ListNode:
    def __init__(self, val, next=None):
        self.val = val
        self.next = next

203.移除連結串列元素

題目:給你一個連結串列的頭節點 head 和一個整數 val ,請你刪除連結串列中所有滿足 Node.val == val 的節點,並返回 新的頭節點 。

解題:

思路:要區別是不是頭節點。可以按兩個規則來刪除,也可以使用虛擬頭節點統一規則。
一、兩個規則

  1. 要刪除的點是頭結點,移動head:移除頭節點是持續操作,有可能前幾個值一樣,用while不是if。
  2. 要刪除的點不是頭結點,移動cur:臨時指標cur應該指向head,cur=head,而不是該刪除的節點,不然找不到刪除節點的上一個節點。
    二、虛擬頭節點,更簡單!
  3. 定義一個虛擬頭節點:dummy_head = ListNode(next = head),頭結點沒有值!
  4. cur=dummyhead,而不是dummyhead→next,原因同上
  5. return dummyNode->next,不要return head,head已經不是我們的頭節點了
    畫個圖好理解!!dummy、head都相當於一個指標下標
點選檢視程式碼
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummyhead=ListNode(next=head)
        cur=dummyhead
        while cur.next:
            if cur.next.val==val:
                cur.next=cur.next.next
            else:
                cur=cur.next
        return dummyhead.next

707.設計連結串列

題目:你可以選擇使用單連結串列或者雙連結串列,設計並實現自己的連結串列。
單連結串列中的節點應該具備兩個屬性:val 和 next 。val 是當前節點的值,next 是指向下一個節點的指標/引用。
如果是雙向連結串列,則還需要屬性 prev 以指示連結串列中的上一個節點。假設連結串列中的所有節點下標從 0 開始。
實現 MyLinkedList 類:
MyLinkedList() 初始化 MyLinkedList 物件。
int get(int index) 獲取連結串列中下標為 index 的節點的值。如果下標無效,則返回 -1 。
void addAtHead(int val) 將一個值為 val 的節點插入到連結串列中第一個元素之前。在插入完成後,新節點會成為連結串列的第一個節點。
void addAtTail(int val) 將一個值為 val 的節點追加到連結串列中作為連結串列的最後一個元素。
void addAtIndex(int index, int val) 將一個值為 val 的節點插入到連結串列中下標為 index 的節點之前。如果 index 等於連結串列的長度,那麼該節點會被追加到連結串列的末尾。如果 index 比長度更大,該節點將 不會插入 到連結串列中。
void deleteAtIndex(int index) 如果下標有效,則刪除連結串列中下標為 index 的節點。

解題:

思路:

  1. get:cur=dummyhead.next,為了方便從第一個實際節點開始遍歷,return cur.val
  2. 報錯:index>self.size而不是>=
點選檢視程式碼
class MyLinkedList:

    def __init__(self):
        self.dummyhead=ListNode()
        self.size=0

    def get(self, index: int) -> int:
        if index<0 or index>=self.size:
            return -1
        cur=self.dummyhead.next
        for i in range(index):
            cur=cur.next
        return cur.val

    def addAtHead(self, val: int) -> None:
        new=ListNode(val,next=self.dummyhead.next)
        self.dummyhead.next=new
        self.size+=1

    def addAtTail(self, val: int) -> None:
        cur=self.dummyhead
        while cur.next:
            cur=cur.next
        new=ListNode(val,next=None)
        cur.next=new
        self.size+=1

    def addAtIndex(self, index: int, val: int) -> None:
        if index<0 or index>self.size:
            return
        cur=self.dummyhead
        for i in range(index):
            cur=cur.next
        new=ListNode(val,next=cur.next)
        cur.next=new
        self.size+=1

    def deleteAtIndex(self, index: int) -> None:
        if index<0 or index>=self.size:
            return
        cur=self.dummyhead
        for i in range(index):
            cur=cur.next
        cur.next=cur.next.next
        self.size-=1

206.反轉連結串列

題目:給你單連結串列的頭節點 head ,請你反轉連結串列,並返回反轉後的連結串列。

解題:

一、雙指標法

  1. cur=head,pre=None
  2. cur.next=pre,如果cur指向pre,那麼cur和下一個節點的連線就沒有了,所以需要一個臨時指標temp在賦值前儲存cur的下一個節點
  3. 先移動pre,再移動cur
點選檢視程式碼
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
         cur=head
         pre=None
         while cur:
            temp=cur.next
            cur.next=pre
            pre=cur
            cur=temp
         return pre

二、遞迴法:在雙指標法基礎上寫的,一一對應,但是比較晦澀難懂,看一下蒜了。

點選檢視程式碼
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        return self.reverse(head, None)
    def reverse(self, cur: ListNode, pre: ListNode) -> ListNode:
        if cur == None:
            return pre
        temp = cur.next
        cur.next = pre
        return self.reverse(temp, cur)

心得:
增刪:cur=dummyhead,指向要插入的前一個節點
查詢:cur=dummyhea.next,方便從第一個實際節點開始比較

相關文章