剑指offer(14):在O(1)时间删除链表节点

O(1)时间删除链表节点的技巧解析
本文介绍了如何在O(1)时间复杂度内删除单向链表中的指定节点。通过分析常规的O(n)解法,提出直接用节点p的后继节点q的值覆盖p,然后更新p的指针指向q,从而实现快速删除。这种方法适用于非尾节点,若要删除尾节点则需要额外处理。代码实现中并未检查节点是否存在,实际应用时需确保节点在链表内。

题目描述:

给定单向链表的头指针head和一个节点指针p,定义一个函数在O(1)时间删除该节点p。

分析:
在单向链表中删除一个节点,最常规的是从链表的头结点开始遍历,找到需要删除的节点并删除,平均时间复杂度为O(n)

推荐解法:
根据需要删除的节点指针p,可以找到p的下一个节点q,将q的值赋值给p后再将p的指针指向q,即用q覆盖p,则达到删除的目的。

如果链表中只有一个节点,在删除该节点后需要把链表的头结点置为null。如果需要删除的是尾节点,即p的下一个节点q为null,则还是需要顺序遍历链表,找到p的前序节点进行删除操作。对于n-1个非尾节点,O(1)时间内可以删除,如果是尾节点则为O(n),平均时间复杂度为[O(1)(n1)+O(n)1]/n,时间复杂度还是O(1)。符合要求。不过该方法并没有判断需要删除的节点是否在链表中,为达到时间复杂度为O(1)的要求,将判断节点是否存在的责任推给了该方法的调用者。

代码:

/**
     * 平均时间复杂度为O(1),删除链表节点
     * @param head 头结点
     * @param nodeToBeDeleted   待删除节点
     */
    public void deleteNode(ListNode head, ListNode nodeToBeDeleted) {
        if(head == null || nodeToBeDeleted == null)
            return;

        //  要删除的节点不是尾节点 O(1)
        if (nodeToBeDeleted.next != null) {
            nodeToBeDeleted.val = nodeToBeDeleted.next.val;
            nodeToBeDeleted.next = nodeToBeDeleted.next.next;
        } else if(head == nodeToBeDeleted) {    // 要删除头节点,而且链表只有一个节点 O(1)
            nodeToBeDeleted = null;
            head = null;
        } else {
            ListNode tmp = head;    //  要删除尾节点,而且链表有多个节点 O(n)
            while (tmp.next != nodeToBeDeleted) {
                tmp = tmp.next;
            }
            tmp.next = null;
            nodeToBeDeleted = null;
        }
    }

参考
1. 何海涛,剑指offer名企面试官精讲典型编程题(纪念版),电子工业出版社

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值