面试经典算法11-删除链表的节点
原题目:LCR 136. 删除链表的节点
公众号:阿Q技术站
问题描述
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
说明:
- 题目保证链表中节点的值互不相同
- 若使用 C 或 C++ 语言,你不需要
free
或delete
被删除的节点
思路
- 判断链表是否为空,若为空直接返回 nullptr。
- 创建一个虚拟头节点
dummy
,并将其指向头节点head
,这样做是为了方便处理头节点的删除操作。 - 初始化两个指针
pre
和cur
,分别指向虚拟头节点和头节点。 - 遍历链表,查找要删除的节点:
- 如果当前节点的值等于要删除的值
val
,则将前一个节点pre
的next
指针指向当前节点的下一个节点cur->next
,即完成删除操作。 - 否则,更新
pre
和cur
指针,继续遍历链表。
- 如果当前节点的值等于要删除的值
- 完成遍历后,更新头节点
head
为虚拟头节点的下一个节点dummy->next
,即删除可能存在的头节点。 - 释放虚拟头节点的内存,避免内存泄漏。
- 返回更新后的头节点
head
。
图解
这里根据示例一给大家做一个图解。
- 初始状态。
- 创建一个虚拟头结点dummy。
- 初始化两个指针
pre
和cur
,分别指向虚拟头节点和头节点。
- 遍历链表,查找要删除的节点:
- 如果当前节点的值等于要删除的值
val
,则将前一个节点pre
的next
指针指向当前节点的下一个节点cur->next
,即完成删除操作。 - 否则,更新
pre
和cur
指针,继续遍历链表。
- 如果当前节点的值等于要删除的值
根据示例,val=5,此时cur->next=5,那么就将cur的上一个节点指向cur的下一个节点,即pre->next=cur->next。
- 完成遍历后,更新头节点
head
为虚拟头节点的下一个节点dummy->next
,即删除可能存在的头节点。
- 释放申请的头结点,返回更新后的头结点head。
参考代码
C++
#include <iostream>
// 链表节点的定义
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
if (!head) return nullptr; // 如果链表为空,直接返回 nullptr
// 创建一个虚拟头节点,方便处理头节点的删除
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* pre = dummy; // 前一个节点指针
ListNode* cur = head; // 当前节点指针
while (cur) {
if (cur->val == val) { // 如果当前节点的值等于要删除的值
pre->next = cur->next; // 将前一个节点的指针指向当前节点的下一个节点
break; // 找到并删除节点后退出循环
}
pre = cur; // 更新前一个节点指针
cur = cur->next; // 更新当前节点指针
}
head = dummy->next; // 更新头节点
delete dummy; // 释放虚拟头节点的内存
return head; // 返回头节点
}
};
// 创建链表
ListNode* createList(std::vector<int>& nums) {
if (nums.empty()) return nullptr;
ListNode* head = new ListNode(nums[0]);
ListNode* cur = head;
for (int i = 1; i < nums.size(); ++i) {
cur->next = new ListNode(nums[i]);
cur = cur->next;
}
return head;
}
// 输出链表
void printList(ListNode* head) {
ListNode* cur = head;
while (cur) {
std::cout << cur->val << " ";
cur = cur->next;
}
std::cout << std::endl;
}
int main() {
// 输入链表
std::vector<int> nums = {4, 5, 1, 9};
ListNode* head = createList(nums);
int val = 5;
// 删除指定值的节点
Solution solution;
head = solution.deleteNode(head, val);
// 输出删除后的链表
printList(head);
return 0;
}
Java
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if (head == null) return null; // 如果链表为空,直接返回 null
// 创建一个虚拟头节点,方便处理头节点的删除
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy; // 前一个节点指针
ListNode cur = head; // 当前节点指针
while (cur != null) {
if (cur.val == val) { // 如果当前节点的值等于要删除的值
pre.next = cur.next; // 将前一个节点的指针指向当前节点的下一个节点
break; // 找到并删除节点后退出循环
}
pre = cur; // 更新前一个节点指针
cur = cur.next; // 更新当前节点指针
}
head = dummy.next; // 更新头节点
return head; // 返回头节点
}
}
public class Main {
// 创建链表
public static ListNode createList(int[] nums) {
if (nums.length == 0) return null;
ListNode head = new ListNode(nums[0]);
ListNode cur = head;
for (int i = 1; i < nums.length; ++i) {
cur.next = new ListNode(nums[i]);
cur = cur.next;
}
return head;
}
// 输出链表
public static void printList(ListNode head) {
ListNode cur = head;
while (cur != null) {
System.out.print(cur.val + " ");
cur = cur.next;
}
System.out.println();
}
public static void main(String[] args) {
// 输入链表
int[] nums = {4, 5, 1, 9};
ListNode head = createList(nums);
int val = 5;
// 删除指定值的节点
Solution solution = new Solution();
head = solution.deleteNode(head, val);
// 输出删除后的链表
printList(head);
}
}
Python
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def deleteNode(self, head: ListNode, val: int) -> ListNode:
if not head:
return None # 如果链表为空,直接返回 None
# 创建一个虚拟头节点,方便处理头节点的删除
dummy = ListNode(0)
dummy.next = head
prev = dummy # 前一个节点指针
curr = head # 当前节点指针
while curr:
if curr.val == val: # 如果当前节点的值等于要删除的值
prev.next = curr.next # 将前一个节点的指针指向当前节点的下一个节点
break # 找到并删除节点后退出循环
prev = curr # 更新前一个节点指针
curr = curr.next # 更新当前节点指针
head = dummy.next # 更新头节点
return head # 返回头节点
# 创建链表
def createList(nums):
if not nums:
return None
head = ListNode(nums[0])
cur = head
for i in range(1, len(nums)):
cur.next = ListNode(nums[i])
cur = cur.next
return head
# 输出链表
def printList(head):
cur = head
while cur:
print(cur.val, end=" ")
cur = cur.next
print()
# 输入链表
nums = [4, 5, 1, 9]
head = createList(nums)
val = 5
# 删除指定值的节点
solution = Solution()
head = solution.deleteNode(head, val)
# 输出删除后的链表
printList(head)