删除链表中重复的结点

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

分析

在链表的面试题中,重要一点是要注意对链表的情况要全部考虑到,或许你在看到上面的例子后按照给出的例子大笔一挥,写出代码后,那么你很可能就已经凉凉。。。

首先我们应该考虑大部分情况,也就是上面例子的情况,但是我们不能急于下笔,应该再考虑,如果在传参的时候,调用者传NULL?在处理链表的过程中,如果链表有一个节点会怎么样,两个呢?要是没有重复的节点呢?如果全是重复的节点呢?还要注意,在没带头节点的情况中,头节点怎么处理?
想完这么多可能会觉得这么多情况怎么处理,不要急,我们一项一项的写,写的时候要注意自己意识到的情况,我们可以用写注释的方式,先写出情况。

对这道题我们来写一下代码~ 分析分析
写链表中我们知道对于单链表访问最大的缺点就是只能单向,从前向后,所以我们删除也是一样,删除当前就得知道当前的上一个节点,那么我们这里采用指针记录的方式。

方法1(粗暴)

我们采用最容易想到的方法,不用考虑时间效率与空间效率问题,就直接用遍历,用一个哈希表结构来记录每个节点对应的值在节点中出现了几次,统计完成后,然后通过哈希表中如果出现次数为大于等于2,再用两个指针一个前一个后开始找对应的值就行了,如果后一个指针指向的节点的值为哈希表中出现次数大于等于2的数,那么前一个指针指向后一个指针的next然后删除后一个指针所指向的节点,让后一个指针重新指向前一个指针的next,就这样就可以完成删除。

虽然这个方法可以,但是时间复杂度为O(N), 空间复杂度为一个哈希表的结构,所以采用这种不是最佳选择。

方法2(三指针法)

采用三个指针来进行遍历,同时删除重复的节点,因为是有序的链表,我们就可以确定,重复的元素肯定是在一块链接,所以我们就可以,用三指针,我们这里就叫
pre、cur、nex 分别代表的是前中后三个指针,我们在考虑的情况中,如果头节点开始就重复,我们就处理很起来多了一种情况就需要额外处理,所以我们添加一个头节点,变成带头节点,保证了头节点开始不会重复,那么我们就可以开是让pre指向带头的节点,cur指向pre的next,nex指向cur的next。

接下来我们就可以看cur是否和nex相等,相等就让nex继续向下走,不相等然后再处理删除,cur开始到nex中间节点都是要删除的(包含cur指向,不包含nex指向)删除,就用到了pre,删除完成让pre指向cur就可以了。

如果cur值与nex值不相等,那么就可以三个指针各自往前移动一个。

方法3

个人感觉这题关键是注意指针的指向,可以定义一个first对象(值为-1,主要用于返回操作后的链表),first.next指向head,定义一个last同样指向first(主要用于操作记录要删除节点的前一个节点),定义一个p指向head,指向当前节点。
操作流程:
①先判断当前p指向与p.next指向是否为空,为空则进入⑤,不为空进入②;
②判断当前节点p的值与与p.next的值是否相等,如果相等,进入③,不相等,进入④
③记录p.val的值为val,循环判断val是否与当前p指向相等,相等的话p = p.next,last.next指向p;
④last指向p,p指向p.next;
⑤返回first.next;

public class Solution {
  
    public ListNode deleteDuplication(ListNode pHead)
    {
         ListNode first=new ListNode(-1);
         first.next=pHead;
         
  //       ListNode later=null;
         
           ListNode pre=first;
        ListNode cur=pHead;
  //          later=cur.next;
        
        if(pHead==null){
            return null;
        }
        
        if(pHead.next==null){
            return pHead;
        }

       while(cur!=null&&cur.next!=null){
        
           if(cur.val==cur.next.val){
 
                int value=cur.val;
                while(cur!=null&&value==cur.val){
                    
                  cur=cur.next;
               pre.next=cur;
                        
                }
        //   pre.next=cur;    
 
            }
           else{
            pre=cur;   
           cur=cur.next;
           
           }
    
        }

            return first.next;  
       }

}

发现了很多问题,用的时间太多了。由于需要考虑的东西太多,思路也不对,于是网上找了思路和代码走一遍。而且 我感觉相同的代码,一直报nullpointerexception错误。

就是测试用例为全部相同的数字时,例如:11111111111
我想当遇到这种链表直接返回null即可,希望有想法的朋友能和我讲一下。

发现,cur!=null必须写在前面,写后面就会报异常。


image.png

怎么踩都是坑啊

你可能感兴趣的:(删除链表中重复的结点)