删除链表中重复的结点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了删除链表中重复的结点相关的知识,希望对你有一定的参考价值。

题目描述

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

分析:

这个题我分了两种情况,一种是头结点不用删除(即头结点和后面结点的值不相等),另一种是头结点需要删除(即头结点和后面结点的值相等)。如果头结点删除了就要重新找新的头结点。
对于这个题的解法,我定义了三个指针 n1、n2、n3。n1 的初始值设为 null,n2 的初始值设为头结点,n3 的初始值设为头结点的下一个结点。n1 的作用是为了删除链表重复的结点,n2 和 n3 负责找到要删除的结点。

头结点不需要删除的情况:

技术图片
n2、n3 的值不相等,n1、n2 和 n3 都往后移一个。


技术图片
此时 n2 和 n3 的值相等,n1、n2 不动,n3 往后移动,直到 n3 的值和 n2 的值不相等。


技术图片
n3 走到了与 n2 值不相等的结点,下一步就直接将 n2 走到 n3 的位置。


技术图片
n2 走到了 n3 的位置,将 n1 的下一个结点指向新的 n2 的位置,就将中间重复的结点删除了。


技术图片
n3 继续往前走,依次列推,直到将链表遍历完。

头结点需要删除的情况:

技术图片
n2、n3 的值相等,n3 往后走直到结点的值与 n2 不相等。


技术图片
走到这一步,链表前两个相等的结点已经被删除了,此时头结点也被删除了,所以就要更新 pHead 的值(这道题我是直接用 pHead 保存的头结点)。


技术图片
n3 往后移一个,走到这里相当于一次循环已经结束了,后面的遍历就和前面的一样,直到链表遍历完。

代码实现:

public ListNode deleteDuplication(ListNode pHead) {
        if (pHead == null) {
            return null;
        }
        ListNode n1 = null;
        ListNode n2 = pHead;
        ListNode n3 = n2.next;
        while (n3 != null) {
            if (n2.val != n3.val) {
                //n2,n3不相等时,n1,n2,n3都往后移动
                n1 = n2;
                n2 = n3;
                n3 = n3.next;
            } else {
                //[n2,n3)是重复区间,注意区间的范围是是左闭右开
                while (n3 != null && n2.val == n3.val) {
                    n3 = n3.next;
                }
                //while循环结束时,n3的已经走到了和n2不相等的位置上,要删除掉重复的数字就直接让n2走到n3上
                n2 = n3;
                if (n1 != null) {
                    //将 n1 的下一个结点指向 n2,就把中间重复的数字删除了
                    n1.next = n2;
                } else {
                    //如果链表的第一位和第二位都相等,头结点也会被删除,n1就变成null了,所以这里就是更新头结点
                    pHead = n2;
                }
                if (n3 != null) {
                    n3 = n3.next;
                }
            }
        }
        return pHead;
    }

以上是关于删除链表中重复的结点的主要内容,如果未能解决你的问题,请参考以下文章

《剑指offer》:[57]删除链表中重复的结点

算法入门15删除链表中重复的结点

链表例题1:删除链表中的重复结点

删除链表中重复的结点

删除链表中重复的结点

删除链表中重复的节点