面试经典算法系列之链表5 -- 删除链表的节点

面试经典算法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++ 语言,你不需要 freedelete 被删除的节点

思路

  1. 判断链表是否为空,若为空直接返回 nullptr。
  2. 创建一个虚拟头节点 dummy,并将其指向头节点 head,这样做是为了方便处理头节点的删除操作。
  3. 初始化两个指针 precur,分别指向虚拟头节点和头节点。
  4. 遍历链表,查找要删除的节点:
    • 如果当前节点的值等于要删除的值 val,则将前一个节点 prenext 指针指向当前节点的下一个节点 cur->next,即完成删除操作。
    • 否则,更新 precur 指针,继续遍历链表。
  5. 完成遍历后,更新头节点 head 为虚拟头节点的下一个节点 dummy->next,即删除可能存在的头节点。
  6. 释放虚拟头节点的内存,避免内存泄漏。
  7. 返回更新后的头节点 head

图解

这里根据示例一给大家做一个图解。

  1. 初始状态。

image-20240218222600488

  1. 创建一个虚拟头结点dummy。

image-20240218222759155

  1. 初始化两个指针 precur,分别指向虚拟头节点和头节点。

image-20240218222940634

  1. 遍历链表,查找要删除的节点:
    • 如果当前节点的值等于要删除的值 val,则将前一个节点 prenext 指针指向当前节点的下一个节点 cur->next,即完成删除操作。
    • 否则,更新 precur 指针,继续遍历链表。

根据示例,val=5,此时cur->next=5,那么就将cur的上一个节点指向cur的下一个节点,即pre->next=cur->next。

  1. 完成遍历后,更新头节点 head 为虚拟头节点的下一个节点 dummy->next,即删除可能存在的头节点。

image-20240218224031064

  1. 释放申请的头结点,返回更新后的头结点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)
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值