[203].移除鏈表元素

 


題目

刪除鏈表中等於給定值 valval 的所有節點。

示例:

輸入: 1->2->6->3->4->5->6, val = 6
輸出: 1->2->3->4->5

 


函數原型

C 的函數原型:

struct ListNode* removeElements(struct ListNode* head, int val){
    
}

 


邊界判斷

struct ListNode* removeElements(struct ListNode* head, int val){
    
}

 


算法設計:哨兵

思路:好的結構設計,可以簡化算法。按照常規的刪除方法,釋放很多元素都適用,唯獨刪除第一個元素,需要特殊處理。更好的方法,是採用哨兵實現通用化。

如果刪除的節點是中間的節點,則問題似乎非常簡單:

  • 選擇要刪除節點的前一個結點 prevprev
  • prevprevnextnext 設置爲要刪除結點的 nextnext


當要刪除的一個或多個節點位於鏈表的頭部時,事情會變得複雜。


可以通過哨兵節點去解決它,哨兵節點廣泛應用於樹和鏈表中,如僞頭、僞尾、標記等,它們是純功能的,通常不保存任何數據,其主要目的是使鏈表標準化,如使鏈表永不爲空、永不無頭、簡化插入和刪除。


在這裏哨兵節點將被用於僞頭。

typedef struct ListNode Node;
struct ListNode* removeElements(struct ListNode* head, int val){
    // 創建哨兵結點
    Node* sentinel = malloc( sizeof(Node) );
    sentinel->next = head;     // 哨兵 -> 頭指針 

    Node* cur = sentinel;
    while( cur->next != NULL ){
        if( cur->next->val == val ){    // 找到了,就刪除結點
            Node* del_node = cur->next;
            cur->next = del_node->next;
            free(del_node), del_node = NULL;
        }else
            cur = cur->next;
    }

    Node* ans = sentinel->next;
    free(sentinel), sentinel = NULL;

    return ans;   
}
  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(1)\Theta(1)
     

算法設計:遞歸

思路:鏈表的增、刪、改、查都可以用遞歸實現,這個也是。

struct ListNode* removeElements(struct ListNode* head, int val){
    if( head == NULL )
        return NULL;
    
    //2、遞去:直到到達鏈表尾部纔開始刪除重複元素
    head->next = removeElements(head->next, val);
    
    //3、遞歸式:相等就是刪除head,不相等就不用刪除
    return head->val==val ? head->next : head;
}
  • 時間複雜度:Θ(n)\Theta(n)
  • 空間複雜度:Θ(n)\Theta(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章