剑指Offer18:删除链表的节点

本文介绍了两种链表节点删除的方法:一种是在O(1)时间内删除指定节点,包括特殊情况处理;另一种是删除排序链表中的重复节点,提供完整的算法思路及代码实现。

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

题目一:在O(1)时间内删除链表节点

链表定义:

class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}

思路:我们知道,常规删除链表节点需要从头开始遍历,需要O(n)的时间。那么要如何才能实现O(1)删除节点呢?
很简单,假设待删除节点为pToBeDeleted,我们可以直接取得它的下一个节点pNext,让pToBeDeleted.val=next.val,再pToBeDeleted.next=pNext.next,最后pNext=null,结果就是删除了pToBeDeleted。
有一个特殊情况,当pToBeDeleted是最后一个节点时,无法如此操作,所以我们要从头节点开始遍历到尾结点来删除它。

void Deleted(ListNode head,ListNode pToBeDeleted)
{
    if (head==null || pToBeDeleted==null)
        return;
    //当被删除结点不是最后一个节点时
    if (pToBeDeleted.next!=null)
    {
        pNext=pToBeDeleted.next;
        pToBeDeleted.val=pNext.val;
        pToBeDeleted.next=pNext.next;
        pNext=null;
    }
    //当被删除结点是头节点时
    else if (pToBeDeleted==head)
    {
        head==null;
    }
    //当被删除结点是最后一个节点时
    else
    {
        ListNode tmp=head;
        while (tmp.next!=pToBeDeleted)
        {
            tmp=tmp.next;   
        }
        tmp.next=null;
        pToBeDeledte=null;
    }
}

进行时间复杂度分析:对于n-1个非尾节点而言,删除需要O(1),对于尾节点,删除需要O(n),所以平均时间复杂度是[(n-1)*O(1)+O(n)]/n=O(1)

题目二:删除链表中重复的节点。在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

思路:很直观,就是遇到重复节点的时候删除,然后注意重复节点前面的节点要进行链接,代码如下:

public ListNode deleteDuplication(ListNode pHead)
    {
        if (pHead==null)
            return null;
        ListNode pPreNode=null;
        ListNode pNode=pHead;
        while (pNode != null)
        {
            ListNode pNext=pNode.next;
            boolean needDelete=false;
            if (pNext != null && pNext.val==pNode.val)
                needDelete=true;

            if (!needDelete)
            {
                pPreNode=pNode;
                pNode=pNode.next;
            }
            else
            {
                int value=pNode.val;
                ListNode pToBeDel=pNode;
                /*删除重复的节点
                while (pToBeDel!=null && pToBeDel.val==value)
                {
                    pNext=pToBeDel.next;
                    pToBeDel=null;
                    pToBeDel=pNext;
                }
                */
                if (pPreNode == null)
                    pHead=pNext;
                else
                    pPreNode.next=pNext;
                pNode=pNext;
            }
        }
        return pHead;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值