18.2 删除链表中重复的结点(剑指 Offer 题解Java版)

题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。

例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
注意重复的结点不保留:并不是将重复结点删除到只剩一个,而是重复结点的全部会被删除。所以
链表1->2->3->3->4->4->5不是1->2->3->4->5
在这里插入图片描述

思路一:采用递归的方法去解决

分为两种情况,第一种如果从第一个节点开始就发生和后面节点相同的情况,则循环跳过所有的相同节点,找到第一个不相同的节点,调用自身返回新的头结点。
第二种情况,如果相邻的节点不相同,则用当前节点指向从下一个节点调用自身方法去检查后面的链表,返回的相应节点,相当于重新构造节点,最后返回头结点。

代码如下:

package 剑指offer.删除链表中重复的结点_18;/*
作者     :XiangLin
创建时间 :13/04/2020 23:16
文件     :Offer18_02.java
IDE      :IntelliJ IDEA
*/

public class Offer18_02 {
    static class ListNode{
         int val;
         ListNode next ;
         ListNode(int val,ListNode next){
          this.val = val;
          this.next = next;
      }
    }
    /**
     * 最简单的方法,递归,从第一个节点每个节点一样的思路
     * 分为两种方式:和相邻节点相同,找到第一个与头节点不同的节点开始递归
     *              和相邻节点不同,保存头节点(用它指向下一个节点,下一个节点由递归得出),从它开始再递归,寻找后面的节点
     * @param phead
     * @return
     */
    public  ListNode deleteDuplication(ListNode phead){
        if (phead == null || phead.next == null){
            return phead;
        }
        //判断相邻是否相等
        if(phead.next.val == phead.val){
            //找到下一个节点是否与第一个节点相同
            ListNode p = phead.next;
            while (p != null && p.val == phead.val){
                p = p.next;
            }
            //改变头结点,以同样的规则进行跳跃
            return deleteDuplication(p);
        }else {
            //相邻节点不相等,保存当前节点,从下一个节点开始是递归,相同的规则去检查
            phead.next = deleteDuplication(phead.next);
            return phead;
        }
    }

    public static void main(String[] args) {
        System.out.println("(不加头结点)有三个节点元素的单链表");
        ListNode node3 = new ListNode(9, null);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(2, node2);
        ListNode pHead = new ListNode(-1, node1);// 头结点
        System.out.println("删除之前");
        printListNode(pHead);
        System.out.println("删除之后");
        Offer18_02 offer18_02 = new Offer18_02();
        offer18_02.deleteDuplication(pHead);
        printListNode(pHead);
    }
    /**
     * 打印链表
     *
     * @param pHead
     */
    private static void printListNode(ListNode pHead) {
        ListNode p = pHead.next;
        while (p != null){
            System.out.print(p.val + " ");
            p = p.next;
        }
        System.out.println();
    }

}

在这里插入图片描述

思路二:

采用非递归实现以上思路,关键是添加一个记录断开位置结点的指针pre,以便以后面重新的连接,或者开始头节点的重新选择。通过循环去移位,依然分为两种情况,相邻节点相等和不相等,不相等则用pre记录下当前节点,并移动当前节点位置。相等的话找到第一个不相等的节点,如果pre为空,则重新设立头结点,不为空则指向当前节点。

代码如下:

package 剑指offer.删除链表中重复的结点_18;/*
作者     :XiangLin
创建时间 :24/04/2020 23:43
文件     :offer18_02.java
IDE      :IntelliJ IDEA
*/

public class offer18_03 {
    static class ListNode{
        int val;
        ListNode next;
        public ListNode(int val,ListNode next){
            this.val = val;
            this.next = next;
        }
    }
/**\
 * 以上思路的非递归实现
 * @param pHead
 * @return
 */
   public ListNode deleteDuplication(ListNode pHead){
       if (pHead == null || pHead.next ==null){
           return pHead;
       }
        ListNode pre = null;
        ListNode cur = pHead;
       //验证cur不为空是保证连续一样时,不为空时才能进入该循环,防止一直找不到没有找到不同数字
       while (cur != null && cur.next != null){
           if (cur.val == cur.next.val){
               int val = cur.val;
               //找到与目前第一节点不同的节点
               while (cur != null &&  cur.val == val){
                   cur = cur.next;
               }
               //头节点重复
               if (pre == null){
                   pHead = cur;
               }else {
                   pre.next = cur;
               }
           }else {
               pre = cur;
               cur = cur.next;
           }
       }
       return pHead;
   }
    public static void main(String[] args) {
        System.out.println("(不加头结点)有三个节点元素的单链表");
        ListNode node3 = new ListNode(9, null);
        ListNode node2 = new ListNode(2, node3);
        ListNode node1 = new ListNode(2, node2);
        ListNode pHead = new ListNode(-1, node1);// 头结点
        System.out.println("删除之前");
        printListNode(pHead);
        System.out.println("删除之后");
        offer18_03 offer18_03 = new offer18_03();
        offer18_03.deleteDuplication(pHead);
        printListNode(pHead);
    }
    /**
     * 打印链表
     *
     * @param pHead
     */
    private static void printListNode(ListNode pHead) {
        ListNode p = pHead.next;
        while (p != null){
            System.out.print(p.val + " ");
            p = p.next;
        }
        System.out.println();
    }

}

在这里插入图片描述
所有巧合的是要么是上天注定要么是一个人偷偷的在努力。

公众号

专注于学习资源、笔记分享,欢迎关注。我们一起成长,一起学习。一直纯真着,善良着,温情地热爱生活,,如果觉得有点用的话,请不要吝啬你手中点赞的权力,谢谢我亲爱的读者朋友
五角钱的程序员,专注于学习资源、笔记分享。

It’s never too late to start over,Even at 3 a.m. on a Saturday,It can also be a new starting point for you。Einstein said:“Time is an illusion.”
重新开始永远都不晚,就算是周六的凌晨3点,也可以成为你新的起点。爱因斯坦说了:“时间是一种幻觉”

2020年4月25日于重庆城口
好好学习,天天向上,终有所获

猜你喜欢

转载自blog.csdn.net/youif/article/details/105501034