[237].刪除鏈表中的節點

 


題目

請編寫一個函數,使其可以刪除某個鏈表中給定的(非末尾)節點,你將只被給定要求被刪除的節點。

現有一個鏈表 – head = [4,5,1,9],它可以表示爲:


示例 1:

輸入: head = [4,5,1,9], node = 5
輸出: [4,1,9]
解釋: 給定你鏈表中值爲 5 的第二個節點,那麼在調用了你的函數之後,該鏈表應變爲 4 -> 1 -> 9.

示例 2:

輸入: head = [4,5,1,9], node = 1
輸出: [4,5,9]
解釋: 給定你鏈表中值爲 1 的第三個節點,那麼在調用了你的函數之後,該鏈表應變爲 4 -> 5 -> 9.

 


函數原型

C的函數原型:

void deleteNode(struct ListNode* node) {}

 


邊界判斷

void deleteNode(struct ListNode* node) {
	if( node == NULL )
		return;
		
	if( node->next == NULL ){	// 要刪除的是最後一個結點(雖然題目說了非末尾結點)
		free(node);
		node = NULL;
		return;
	}
}

 


算法設計:鏈表刪除結點的特殊情況,改變值再刪除

這題和一般鏈表刪除結點情況不同。

通常鏈表刪除結點是通過待刪除結點前一個結點,來檢測刪除哪一個結點,對於前一個結點它的 next 指針直接指向要刪除結點的下一個結點,把要刪除的這個結點跨過去即可。

如,刪除結點 3


通常會通過 3 前面的 2 來定位,而後會把指向 2cur 指針指向 4,跨過 3

這道題不太一樣,直接給定 3 這個結點,我們無法獲取 2 這個結點的信息。

咋辦?

我們可以動的就只有當前結點的指針。


把後面的值賦值過來,再刪除掉後面的指針即可。

void deleteNode(struct ListNode* node) {
	if( node == NULL )
		return;
		
	if( node->next == NULL ){	// 要刪除的是最後一個結點(雖然題目說了非末尾結點)
		free(node);
		node = NULL;
		return;
	}
	
	node->val = node->next->val;	// 用下一個值覆蓋
    struct ListNode* del_node = node->next;
	node->next = node->next->next;  
	free(del_node);
    del_node = NULL;    // free指針後,指針的值是一個隨機值,爲防止野指針,重新初始化
}

在面向對象的語言中,已知 node 但無法訪問 node 的上一個節點,因此不能修改上一個節點的 next 屬性。

於是得把 node節點的值用下一個節點的值去覆蓋掉,然後把重複值的 node.next 給刪除掉也可以實現刪除結點。

但在 C 語言中,因爲是指針和結構體來表示鏈表,因此 node 和之前節點的 next 指向了內存中的同一地址,所以只要對這個地址做修改,上一個節點的 next 也同時被修改了。

*node = *(node->next);

完整代碼:

void deleteNode(struct ListNode* node) {	
	*node = *(node->next);	
	// *號把 [node->next] 裏面的 值(val)、指向下個結點(node->next->next) 都賦值給了 [node],但 [node] 的地址沒變。
}
  • 時間複雜度:Θ(1)\Theta(1)
  • 空間複雜度:Θ(1)\Theta(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章