題目
刪除鏈表中等於給定值 的所有節點。
示例:
輸入: 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){
}
算法設計:哨兵
思路:好的結構設計,可以簡化算法。按照常規的刪除方法,釋放很多元素都適用,唯獨刪除第一個元素,需要特殊處理。更好的方法,是採用哨兵實現通用化。
如果刪除的節點是中間的節點,則問題似乎非常簡單:
- 選擇要刪除節點的前一個結點
- 將 的 設置爲要刪除結點的
當要刪除的一個或多個節點位於鏈表的頭部時,事情會變得複雜。
可以通過哨兵節點去解決它,哨兵節點廣泛應用於樹和鏈表中,如僞頭、僞尾、標記等,它們是純功能的,通常不保存任何數據,其主要目的是使鏈表標準化,如使鏈表永不爲空、永不無頭、簡化插入和刪除。
在這裏哨兵節點將被用於僞頭。
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;
}
- 時間複雜度:
- 空間複雜度:
算法設計:遞歸
思路:鏈表的增、刪、改、查都可以用遞歸實現,這個也是。
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;
}
- 時間複雜度:
- 空間複雜度: