剑指Offer(八)删除链表的节点 删除链表重复节点

剑指offer(八) 删除链表的节点 删除链表重复节点

题目:

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

思路:

遍历一遍等于白给 O(n)

假设 1-2-3-4-5-6-7-8-9

当删除 2 这个节点的时候, 把2 之后的第一个节点3复制到一个temp节点,然后将temp 这个节点里的值复制给2,将temp的指针赋给 2 ,也就是2 节点的值变为3,其指向变成了4.

3-4-5-6-7-8-9

1 - 2 -3-4-5-6-7-8-9 删除之后就 相当于1-3-4-5-6-7-8-9

对于n-1个非尾节点,我们可以在0(1)内将后一个节点复制覆盖给删除的节点,对于最后一个节点,我们还是需要去遍历链表找到他,复杂度还是0(n)

平均时间复杂度 【(n-1)* O(1) + O(n) 】 / n

总的平均时间复杂度为 O(1)

代码:


public void deleteNode(ListNode head, ListNode node)
{
    if (head==null||node==null)
    //输入有误  返回
    {
       return;
    }
    if (head==node)
    //删除节点就是头节点
    {
        head =null;
        node = null;
        return;
    }
    if (node.next!=null)
    //删除节点在链表中
    {
        ListNode node1 = node.next;
            //node1 此时是待删节点的下一个节点
            node.val = node1.val;
            // 将待删节点的下一个节点 的 val 赋值给  待删节点
            node.next = node1.next;
            //将待删节点的下一个节点 的 指针 赋给 待删节点
        }else
    {
        ListNode temp=head;
        while(temp.next!=node)
                 temp=temp.next;
        temp.next=null;
    }
}

题目:

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

例如:1 -> 2 -> 3 -> 3 -> 4
删除后是 1 -> 2 -> 4

思路:

维持两个指针,一个指针为要当前节点的前一个指针,一个指向当前节点.

首先初始化,pre指针为null,而cur指针指向链表的头.

当cur指向的节点的next不为空,也就是它不只有一个节点,继续

​ 不为空,且当前节点和下一个节点的值相同,即重复

​ while循环,直到找到一个和当前节点的值不一样的节点

​ 如果pre==null 那就说明已经遍历的所有节点都是重复的

​ 将当前节点作为phead 节点

​ 如果pre != null

​ 将 pre的next指向当前节点.

​ 没有和下一个节点相同.没有重复

​ pre指向当前节点,cur指向下一个节点.继续遍历

代码:

    //删除链表里的重复节点
    //非递归版本
    public static ListNode deleteRepeatNode1(ListNode pHead)
    {
        ListNode pre = null;
        ListNode cur = pHead;
        while (cur != null)
        {
            if (cur.next != null && cur.next.val == cur.val)
            {
                while (cur.next != null && cur.next.val == cur.val)
                {
                    cur = cur.next;
                }
                cur = cur.next;
                if (pre == null) pHead = cur;
                else pre.next = cur;
            }
            else
            {
                pre = cur;
                cur = cur.next;
            }
        }
        return pHead;
    }
    //https://www.cnblogs.com/yongh/p/9672004.html#_label2

//删除链表里的重复节点
    //递归版本
    public static ListNode deleteDuplication(ListNode pHead)
    {
        if (pHead==null)
        //输入有误  返回
        {
            return null;
        }
        ListNode next=pHead.next;
        if(pHead.val==next.val)
        {
            while(next!=null&&pHead.val==next.val)
                //需要先判断是否为空
            {
                next=next.next;
                //找到下一个
            }
            return deleteDuplication(next);
        }else
        {
            pHead.next=deleteDuplication(next);
            return pHead;
        }
    }


public static void main(String[] args)
    {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 =new ListNode(3);
        ListNode node4 =new ListNode(3);
        ListNode node5 =new ListNode(3);
        ListNode node6 =new ListNode(3);
        ListNode node7 =new ListNode(3);

        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;
        node5.next=node6;
        node6.next=node7;

        ListNode old = node1;
        while (old!=null)
        {
            System.out.print(" "+old.val );
            old=old.next;
        }
        System.out.println();
        deleteDuplication(node1);

        while (node1!=null)
        {
            System.out.print(" "+node1.val );
            node1=node1.next;
        }
    }

测试用例

我们测试要尽可能的全面
1)传NULL
2)只有一个节点
3)头节点开始就有重复
4)中间节点重复
5)尾部节点重复
6)链表中没有重复链表
7)所有节点都是重复的

https://blog.csdn.net/gangstudyit/article/details/80623477

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值