数据结构与算法分析笔记与总结(java实现)--链表8:对排序链表删除重复结点问题

来源:互联网 发布:painter是什么软件 编辑:程序博客网 时间:2024/06/07 05:54

思路:所谓删除结点node只需要将node前面结点的next指针直接指向node结点的下一个结点即可,不需要将node置null或者将node的next属性置为null,因为被删除结点由于不再被上一个结点引用,就会成为不可达的死对象从而会被GC自动回收。

这里关键是如何判断重复结点,并且将指针指向下一个不重复的结点;判断连续的重复很复杂:

这道题目较复杂,关键是对于几种特殊类型的全面考虑,即便捷情况的考虑:

pnext为null怎么办?

如果是pcur的第一个pnext指针为null,表示为1233445这种情况,即最后一个结点没有重复;即pcur是没有重复的结点,且是最后一个结点,此时对应情形①。于是将pcur连接到retainedNode后面然后返回dummy链表即可。

如果是在pnext对重复的多个结点进行移动时出现pnext为null,表示为12334555这种情况,即最后的结点重复,此时对应情形②,由于不会再有新的结点出现了,而最后一个结点又不是单独的结点,因此所有工作已经结束了,可以直接结束循环返回dummy链表,如果不及时返回会进入情况①的else模块中,导致retainedNode又被附上了pcur的值,而pcur实际上是重复值!

情况③是普通的情况,即用来寻找不重复的结点。即要有一个指针pnext来遍历判断后面的几个结点是否是重复的,如果有重复就向下移动,直到有不重复的结点,将它作为新的pcur,并将它连接到retainedNode链表上面。

/*

 public class ListNode {

    int val;

    ListNode next = null;

    ListNode(int val) {

        this.val = val;

    }

}

*/

// 该方法用来删除链表中重复的结点,最终返回的链表中没有重复的结点1223445-->135

         public ListNodedeleteDuplication(ListNode pHead) {

// 特殊的输入

                   if (pHead ==null)  return null;

                   // 由于需要构造返回一条新的链表,因此使用固定技巧

                   ListNodedummy = new ListNode(-1);

                   // 保留下来的结点组成的链表

                   ListNoderetainedNode = dummy;

                   // 当前正在判断是否重复的结点

                   ListNodepcur = pHead;

 

// 找准确循环条件究竟是什么,这里是对每个当前结点进行遍历:先pcur!=null,再求出pcur的next结点

                   while (pcur !=null) {

// 当前结点之后的结点,需要逐个与pcur进行比较

                            ListNodepnext = pcur.next;

/**

* pcur之后的值与他相同,pcur必然是重复结点,还需要将重复部分全部遍历完 共有几种情况:

1.pnext是null,表示pcur是最后一个结点; 

2.pnext!=null但是pcur.val ==pnext.val表示下一个结点与pcur重复; 

3.pnext!=null但是pcur的下一个值与他不同,表示pcur是一个不重复的点;  

每种情况要分别处理。

 */

                            if (pnext!= null && pcur.val == pnext.val) {

                                     while(pnext != null && pcur.val == pnext.val) {

                                               //pnext指针不断向下移动

                                               pnext= pnext.next;                                           //情况

                                     }

//当pnext指针不再往下移动时有两种情况:1.pnext为null;2.此时pnext终于不再是 重复值了,是一个新的值,分别处理。

//如果pnext为null,那么表示是尾部相同的数例如123444,应该立即结束循环返回, 否则会进入12333445的else模块,这两种情形是不同的。

                                     if(pnext != null) {   

                                               pcur= pnext;

                                               pnext= pcur.next;

                                     }else {            //情况

                                               returndummy.next;

                                     }

                            } else if(pnext != null && pcur.val != pnext.val) {

//如果pcur之后的值与pcur就不同,那么说明pcur是唯一的,不重复,需要保留

//特别注意:要把pcur结点连接到retainedNode时,需要先将pcur后面的结点关系切断,否则如果pcur是retainedNode上面的最后一个结点,那么会把pcur后面所跟的结点全部带到retainedNode链表中来;例如12233455可能会得到1455,因为当4被连接到retainedNode上面时会将55也带着。

                                     pcur.next = null;

                                     retainedNode.next= pcur;

                                     retainedNode= retainedNode.next;

                                     //此时也需要向下推进,判断下一个结点是否重复

                                     pcur= pnext;

                                     pnext= pcur.next;

                            } else {

                            // 即此时pnext==null,说明pcur已经是最后一个结点了,这个结点必然是不重复的结点,即最后一个结点是一个单独的结点,例如12333445 //情形

                                     retainedNode.next= pcur;

                                     retainedNode= retainedNode.next;

                                     returndummy.next;

                            }

                   }

                   return dummy.next;

         }}


牛人简洁代码:再理解

public static ListNode deleteDuplication(ListNode pHead) {       

        ListNode first = newListNode(-1);//设置一个trick

        first.next = pHead;

        ListNode p = pHead;

        ListNode last = first;

        while (p != null &&p.next != null) {

            if (p.val == p.next.val){

                int val = p.val;

                while (p!=null&&p.val == val)

                    p = p.next;

                last.next = p;

            } else {

                last = p;

                p = p.next;

            }

        }

        return first.next;

}

1 0