【leetcode】剑指 Offer 18. 删除链表的节点

Myth丶恋晨 2022-11-15 11:59 214阅读 0赞

剑指 Offer 18. 删除链表的节点

  • 题目难度:简单
  • 方法一

链接:https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof/
来源:力扣(LeetCode)图解算法数据结构

题目难度:简单

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。

返回删除后的链表的头节点。

示例 1:

  1. 输入: head = [4,5,1,9], val = 5
  2. 输出: [4,1,9]
  3. 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9

示例 2:

  1. 输入: head = [4,5,1,9], val = 1
  2. 输出: [4,5,9]
  3. 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.

限制:

  1. 题目保证链表中节点的值互不相同

模板

  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) { val = x; }
  7. * }
  8. */
  9. class Solution {
  10. public ListNode deleteNode(ListNode head, int val) {
  11. }
  12. }

方法一

思路:

  • 整体思路是使用双指针,前指针pre 和 当前指针cur,当前方指针遇到要删除的值时,则使用后方指针重新构造连接并跳过该值

    • 首先判断头指针是否为 null,如果为空则直接返回 null
    • 如果头指针 head.val 即为要删除的值,则直接返回 head.next 即可
    • 设节点 cur 的前驱节点为 pre 和后继节点 cur.next
    • 双指针一直遍历链表,直到遍历到链表结尾或等于要删除的值时则跳出循环
    • 如果找到要删除的值,则令 pre.next = cur.next,相当于将链表中的值删除

解题思路:

本题删除值为 val 的节点分需为两步:定位节点、修改引用。

  1. 定位节点: 遍历链表,直到 head.val == val 时跳出,即可定位目标节点。
  2. 修改引用: 设节点 cur 的前驱节点为 pre ,后继节点为 cur.next ;则执行 pre.next = cur.next ,即可实现删除 cur 节点。
    在这里插入图片描述

算法流程:

  1. 特例处理: 当应删除头节点 head 时,直接返回 head.next 即可。
  2. 初始化pre = head , cur = head.next
  3. 定位节点: 当 cur 为空 cur 节点值等于 val 时跳出。

    1. 保存当前节点索引,即 pre = cur
    2. 遍历下一节点,即 cur = cur.next
  4. 删除节点: 若 cur 指向某节点,则执行 pre.next = cur.next ;若 cur 指向 n u l l null null ,代表链表中不包含值为 val 的节点。
  5. 返回值: 返回链表头部节点 head 即可。

复杂度分析:

  • 时间复杂度 O ( N ) O(N) O(N): N N N 为链表长度,删除操作平均需循环 N / 2 N/2 N/2 次,最差 N N N 次。
  • 空间复杂度 O ( 1 ) O(1) O(1) : cur, pre 占用常数大小额外空间。

    class Solution {

    1. public ListNode deleteNode(ListNode head, int val) {
    2. if(head.val == val) return head.next;
    3. ListNode pre = head, cur = head.next;
    4. while(cur != null && cur.val != val) {
    5. pre = cur;
    6. cur = cur.next;
    7. }
    8. if(cur != null) pre.next = cur.next;
    9. return head;
    10. }

    }

    class Solution {

    1. public ListNode deleteNode(ListNode head, int val) {
    2. //边界条件判断
    3. if (head == null) return head;
    4. //如果要删除的是头结点,直接返回头结点的下一个结点即可
    5. if (head.val == val) return head.next;
    6. ListNode cur = head;
    7. //找到要删除结点的上一个结点
    8. while (cur.next != null && cur.next.val != val) {
    9. cur = cur.next;
    10. }
    11. //删除该结点
    12. if(cur.next != null)
    13. cur.next = cur.next.next;
    14. return head;
    15. }

    }

发表评论

表情:
评论列表 (有 0 条评论,214人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Offer18:删除节点

    思路:一般删除链表的节点,通过O(n)遍历到删除链表的前一个节点,然后将前一个节点的next指向删除节点的next,再删除需要删除的节点。 但是,如果删除的节点指针知道,那么