链表 - 203. 移除链表元素(C#和C实现)
题目描述
删除链表中等于给定值 val
的所有节点。
解题思路
使用迭代或递归的方式遍历链表,检查每个节点的值是否等于目标值 val
,若是则删除该节点。需要注意的是,删除节点时需要更新前一个节点的 next
指针。
解题步骤
迭代方法:
- 初始化一个虚拟头节点
dummy
,使其next
指向链表的头节点。 - 初始化指针
prev
,初始指向虚拟头节点。 - 遍历链表,当发现节点值等于目标值
val
时,删除该节点,即更新prev
的next
指针。 - 返回虚拟头节点的
next
,即为删除目标值后的新链表。
递归方法:
- 使用递归遍历链表,对每个节点进行判断,若节点值等于目标值
val
,则删除该节点。 - 递归调用下一个节点。
- 返回新链表的头节点。
C#代码实现(迭代方法)
public ListNode RemoveElements(ListNode head, int val) {
// 创建一个虚拟头节点
ListNode dummy = new ListNode(0);
// 将虚拟头节点指向头节点
dummy.next = head;
// 创建一个前一个节点
ListNode prev = dummy;
// 遍历链表
while (prev.next != null) {
// 如果当前节点的值等于val
if (prev.next.val == val) {
// 将当前节点指向下一个节点
prev.next = prev.next.next;
} else {
// 否则,前一个节点指向当前节点
prev = prev.next;
}
}
// 返回头节点
return dummy.next;
}
C代码实现(迭代方法)
struct ListNode* removeElements(struct ListNode* head, int val) {
// 创建一个虚拟头节点
struct ListNode* dummy = malloc(sizeof(struct ListNode));
dummy->next = head;
// 创建一个前一个节点指针
struct ListNode* prev = dummy;
// 遍历链表
while (prev->next != NULL) {
// 如果当前节点的值等于val
if (prev->next->val == val) {
// 创建一个临时节点
struct ListNode* temp = prev->next;
// 将当前节点指向下一个节点
prev->next = prev->next->next;
// 释放临时节点
free(temp);
} else {
// 否则,前一个节点指向下一个节点
prev = prev->next;
}
}
// 返回虚拟头节点的下一个节点
return dummy->next;
}
C#代码实现(递归方法)
public ListNode RemoveElements(ListNode head, int val) {
// 如果链表为空,则返回null
if (head == null) {
return null;
}
// 递归调用,删除下一个节点
head.next = RemoveElements(head.next, val);
// 如果当前节点的值为val,则返回下一个节点,否则返回当前节点
return head.val == val ? head.next : head;
}
C代码实现(递归方法)
struct ListNode* removeElements(struct ListNode* head, int val) {
// 如果链表为空,则返回空
if (head == NULL) {
return NULL;
}
// 递归调用,删除链表中下一个节点值为val的节点
head->next = removeElements(head->next, val);
// 如果当前节点值为val,则返回下一个节点,否则返回当前节点
return head->val == val ? head->next : head;
}
时间复杂度和空间复杂度
- 时间复杂度:O(n),其中 n 是链表的长度。每个节点最多被访问一次。
- 空间复杂度:O(1)。除了常数级别的变量,算法的空间复杂度是常数级别的。
参与点评
读者朋友们,如果您在阅读过程中,对文章的质量、易理解性有任何建议,欢迎在评论区指出,我会认真改进。