剑指笔记——18删除链表的节点

本文介绍两种高效的链表操作方法:一是O(1)时间内删除指定节点;二是删除排序链表中的重复节点。前者通过覆盖节点值实现快速删除,后者利用标志位判断并跳过重复节点。

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

思路:最简单的一种想法是从链表的头结点开始遍历,找到要删除节点的前一个节点。但是这种方法的时间复杂度是O(n),不符合题目的要求。其实我们可以不需要找到删除节点的前一个指针,只需要将删除节点i后面一个节点j的值和它的下一个节点信息赋给要删除的节点i,再删除节点j就可以了。对于在链表中间的节点来说,时间复杂度是O(1),对于最后一个节点,仍然要从头结点开始遍历,时间复杂度是O(n),这样一来总的时间复杂度仍然是O(1),符合题目要求。

代码:

public void deleteNode(ListNode head, ListNode deListNode) {
if (deListNode == null || head == null)
return;
if (head == deListNode) {
head = null;
} else {
// 若删除节点是末尾节点,往后移一个
if (deListNode.nextNode == null) {
ListNode pointListNode = head;   //如果要删除的节点就是头结点的话,是不是就会直接到这一步?那么头结点之后的节点是不是就没有了呢?
while (pointListNode.nextNode.nextNode != null) {
pointListNode = pointListNode.nextNode;
}
pointListNode.nextNode = null;
} else {

deListNode.data = deListNode.nextNode.data;
deListNode.nextNode = deListNode.nextNode.nextNode;
}
}
}

题目2:删除链表中的重复节点

在一个排序链表中,如何删除重复的节点。

思路:注意在上面的题中已经说明是排序链表,也就是说重复的元素一定是排在一起的,这是一个前提。我们从头到尾遍历整个链表,如果当前节点的值与下一个节点的值相同,那么它们就是重复节点,都可以被删除。为了保证删除后的链表仍然是相连的,我们要把当前节点的前一个节点和后面值比前面大的节点相连。对于链表的部分要注意细节,很容易写错。代码原文链接如下:https://blog.youkuaiyun.com/zjkC050818/article/details/72897164

代码:

public ListNode deleteDuplication_3(ListNode pHead) {
        if(pHead==null||pHead.next==null)
            return pHead;
        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;   //一个辅助节点用来找到不是重复节点的下一个节点,结果放在pNext中
                while(pToBeDel!=null&&pToBeDel.val==value){
                    pNext=pToBeDel.next;
                    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、付费专栏及课程。

余额充值