剑指offer之删除链表节点

本文介绍了一种在O(1)时间内删除单向链表中指定节点的方法,通过对下一个节点值的复制来实现节点的删除,同时讨论了特殊情况下的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


title: 删除链表节点
date: 2018-08-06 08:28:59
tags: 剑指offer

1. 题目

在 O(1) 时间内删除链表节点。

给定单向链表节点的头指针和一个节点指针(使用 java 实现,因此我的代码中头结点作为一个变量定义在类中),定义一个函数在 O(1) 时间内删除该节点。

2. 思路

在单向链表中删除节点按照常规的思路来说就是从头开始遍历,查找到需要删除的节点,并在链表中删除该节点。但是这种做法的时间复杂度为 O(N),并不符合题目要求,因此需要考虑一下其他的思路。

首先,看一下链表内部使用的数据结构:

private class Node{
    private Object value;
    private Node next;

    public Node(Object value,Node next){
        this.value = value;
        this.next = next;
    }
}

一个节点包含这个节点的值以及下一个节点的引用。如果要删除这个节点的值,可以通过将下一个节点的内容复制到要删除的这个节点,通过这样的动作也是可以删除节点的。例如,有这样的一个链表:

1 -> 2 -> 3 -> 4 -> 5

如果要删除 3 这个节点,那么,我们可以将 4 这个节点的值覆盖 3 这个节点的值,用 4 这个节点的 next 变量覆盖 3 这个节点的 next 变量,这个过程下来,链表中就将 3 这个节点删除了。

但是这个过程需要注意,如果这个节点是最后一个节点,就没办法通过上述的方法来完成,只能通过常规的方法来解决了。

还有一个情况需要注意,如果这个节点是头结点并且整个链表中只有一个节点,这时候我们就需要将链表的头结点置为空。代码的实现如下:

private Node head;
private Node tail;

public void deleteNode(Node toBeDelete){
    if(head==null || toBeDelete==null)
        return;
    if(toBeDelete.next!=null){
        Node nextNode = toBeDelete.next;
        toBeDelete.value = nextNode.value;
        toBeDelete.next = nextNode.next;
    }else if(head.value.equals(toBeDelete.value)){
        head = null;
        tail = null;
    }else{
        Node currentNode = head;
        while(!toBeDelete.value.equals(currentNode.next.value)){
            currentNode = currentNode.next;
        }
        currentNode.next = null;
    }
}

// 打印链表的方法
public void printLinkList(){
    Node currentNode = head;
    while(currentNode!=null){
        System.out.println(currentNode.value);
        currentNode = currentNode.next;
    }
}

// 链表添加元素的方法
public void add(Object value){
    Node temp = new Node(value,null);
    if(head==null){
        head = temp;
        tail = temp;
    }else{
        tail.next = temp;
        tail = tail.next;
    }
}

3. 注意点

这个方法的时间复杂度是不是 O(1) 呢?答案是肯定的,其时间复杂度为 [ (n-1)*O(1) + O(n) ] / n = O(1)。

这个思路是基于一个假设上实现的,就是要删除的元素需要在链表内,为了符合时间复杂度为 O(1) 的要求,就没办法在函数中进行判断,因此需要由调用该函数的人来保证。这在面试过程中可以和面试官进行探讨,可以让面试官对我们有一个更好的印象。

详细的代码可以上 github 上进行下载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值