• 删除排序链表中重复数字节点,只保留原始链表中 没有重复出现的数字(二)


    引用:原文链接:https://blog.csdn.net/dadajixxx/article/details/87551738

    /*题目
    * 在一个排序的链表中,存在着重复的节点,请删除该链表中重复的节点,重复的节点不保留,返回链表头指针
    * 示例1:1 -> 2 ->  2 ->  3 ->  3 ->  4 ->  5      -------->删除后: 1 ->  4 ->  5

    * 示例2: 1->1->1->2->3      --------->删除后:2->3

     * 

    * */

    解法1:

    原文链接:https://blog.csdn.net/if_i_were_a/article/details/89093043

     思路:与上一道题相比,这道题不同之处在于他要把所有的重复值节点都删完,前一道题的思路在于当前的值跟下一个值比较,如果重复,删除下一个,如果不重复,就继续遍历下一个元素。但是相对于这道题,当前的值即使跟下一个不相等,也有可能与之前重复过的相等。那么如何保证在这种情况下的时间复杂度为0(1)呢,可以使用一个计数器,如果有与当前节点重复的节点,删除掉重复节点之后(因为该链表是有序的,所以重复的就是当前节点的下一个),计数器的值加一。当前节点重复值删除完之后,判断当前节点是否需要删除就是判断计数器的值是否为0,如果不是0则删除该节点。然后继续遍历

    有两种特殊情况,当前节点有重复在链表的头和链表的尾。当为头的时候,因为该链表是不带表头的节点,所以有两种解法,加虚拟表头结点或者分为判断是否为为表头结点,是和不是分为两种情况。对于尾节点来说,因为出循环之后还要判断尾节点是否重复过,如果重复过,删除尾节点。

    public static ListNode deleteDuplicates1(ListNode head) {
      //添加一个虚拟的表头结点
      ListNode tempHead = new ListNode(0);
      tempHead.next = head;
      //pre之前虚拟头结点,记录元素的前一个位置,如果要删除当前元素,需要前一个位置的指针
      ListNode cur = head, pre = tempHead;
      //计数器的初始值置为0
      int count = 0;
      //当前链表为空或者遍历到链表的最后一个元素时
      while (cur != null && cur.next != null) {
        //如果当前节点和下一个结点相等,删除下一个结点,计数值加1
        if (cur.val == cur.next.val) {
          cur.next = cur.next.next;
          count++;
        } else {
          //不相等的情况下需要判断计数值是否为0来确定是否需要删除当前节点
          if (count > 0) {
            pre.next = cur.next;
            count = 0;
          } else {
            pre = cur;
          }
          cur = cur.next;
        }
      }
      //判断尾节点是否需要删除
      if (count > 0) {
        pre.next = cur.next;
      }
      //返回去除虚拟头结点的链表
      return tempHead.next;
    }
    -----------------------------------------------解法1的完整代码------start-----------------------------------------------

    原文链接:https://blog.csdn.net/if_i_were_a/article/details/89093043

    public class Num83 {
      public static void main(String[] args) {
        int[] arr = new int[]{1, 1, 1, 2, 3, 5};
        //删除链表中的重复元素,保留一个
        ListNode head = new ListNode(arr);
        head = deleteDuplicates1(head);
        System.out.println(head.toString());
      }
      public static ListNode deleteDuplicates1(ListNode head) {
        //添加一个虚拟的表头结点
        ListNode tempHead = new ListNode(0);
        tempHead.next = head;
        //pre之前虚拟头结点,记录元素的前一个位置,如果要删除当前元素,需要前一个位置的指针
        ListNode cur = head, pre = tempHead;
        //计数器的初始值置为0
        int count = 0;
        //当前链表为空或者遍历到链表的最后一个元素时
        while (cur != null && cur.next != null) {
          //如果当前节点和下一个结点相等,删除下一个结点,计数值加1
          if (cur.val == cur.next.val) {
            cur.next = cur.next.next;
            count++;
          } else {
            //不相等的情况下需要判断计数值是否为0来确定是否需要删除当前节点
            if (count > 0) {
              pre.next = cur.next;
              count = 0;
            } else {
              pre = cur;
            }
            cur = cur.next;
          }
        }
        //判断尾节点是否需要删除
        if (count > 0) {
          pre.next = cur.next;
        }
        //返回去除虚拟头结点的链表
        return tempHead.next;
      }


      static class ListNode {
        int val;
        ListNode next;

        ListNode(int x) {
        val = x;
      }

      public ListNode(int[] arr) {
        if (arr == null || arr.length == 0)
          throw new IllegalArgumentException("arr can to be empty");
        this.val = arr[0];
        ListNode cur = this;
        for (int i = 1; i < arr.length; i++) {
          cur.next = new ListNode(arr[i]);
          cur = cur.next;
        }
      }

      @Override
      public String toString() {
        StringBuilder res = new StringBuilder();
        ListNode cur = this;
        while (cur != null) {
          res.append(cur.val + "->");
          cur = cur.next;
        }
        res.append("NULL");
        return res.toString();
      }
      }
    }

    ------------------------------------------------解法1完整代码--------end------------------------------------------------

    解法2

    /*思路
    * 遍历节点的同时判断当前节点与下一个节点是否相同,如果相同则删除,
    * 删除方法 使用相同节点的前一个节点,指向相同节点的下一个节点如图
    *
    * */

    public class offer57 {

      class ListNode{
        int val;
        ListNode next=null;
        public ListNode(){ }
        public ListNode(int val){
        this.val=val;
        }
      }

    public ListNode deleteDeplication(ListNode pHead){

      if (pHead == null)  return null;

      //注意备用头结点,头结点可能被删除
      ListNode first = new ListNode(-1);

      first.next = pHead;
      ListNode p = pHead;
      //前节点
      ListNode preNode = first;

      while (p != null && p.next != null){
        if (p.val == p.next.val){ //两节点相等

          int val = p.val; //记录val用于判断后面节点是否重复
          while(p != null && p.val == val){ //这一步用于跳过相等的节点,用于删除
            p = p.next;
          }
          preNode.next = p; //删除操作,前节点的next直接等于现在的节点,把中间的节点直接跨过
        }else {
          preNode = p;
          p = p.next;
        }
      }
      return first.next;
      }
    }

    解法3:双指针法(也可以说是三指针法,设置的头结点需要参与元素链接,最后还需要输出) 设置一个新的头结点,使得链表元素进行链接和输出 当前后两个指针相同时,移动下一个指针到两个元素不相同,然后使用设置的头结点进行链接,得以越过相同元素 如果两个指针不相同,就移动处理,指针跟随

    class Solution {
      public ListNode deleteDuplicates(ListNode head) {
        if(head == null || head.next == null) return null;

        ListNode dummy = new ListNode(-1); //为链表创建一个新的头,return dummy.next 来带领整个链表
        dummy.next = head;
        ListNode current = head;
        ListNode index = dummy;

        //index在前面,所以判断index是否为null 就行

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

          //相等,将index移动向下一位
          if(current.val == current.next.val)  {
            while(current.next!= null && current.val == current.next.val) {current = current.next;}
            index.next = current.next;
            current = current.next;

          }  else  {

               index = current;
            current = current.next;
           }
        }
      return dummy.next;

      }

    }

    解法4:三指针法(利用三个指针和标志位flag进行处理)

    public ListNode deleteDuplicates(ListNode head) {

      ListNode pre = null;
      ListNode current = head;

      while (current != null) {
        ListNode nex = current.next; //通过while循环始终让nex作为最快的指针,注意进行null的判断
        boolean flag = false; //使用flag作为nex和cur的标志位
        while (nex != null && current.val == nex.val) {
          flag = true;
          nex = nex.next;
        }
        //对重复元素进行处理
        if (flag) {

          //判断不是刚开始,进行和nex结点的连接
          if (pre != null) { 

            pre.next = nex;

           } else { //头部

            head = nex; 

          }

          current = nex;
        } else { //对非重复元素进行连接和跳跃
          pre = current;
          current = current.next;
        }
      }

      //返回头指针
      return head;
    }

    解法5递归方法

    public static ListNode deleteDuplicates(ListNode head) {
      //baseCase
      if (head == null || head.next == null) { return head;}

      ListNode next = head.next;
      //如果是这种情况
      // 1 --> 1 --> 1 --> 2 --> 3
      // head next
      //1.则需要移动next直到出现与当前head.value不相等的情况(含null)
      //2.并且此时的head已经不能要了,因为已经head是重复的节点
      //--------------else-------------
      // 1 --> 2 --> 3
      // head next
      //3.如果没有出现1的情况,则递归返回的节点就作为head的子节点
      if (head.value == next.value) {
      //1
        while (next != null && head.value == next.value) { next = next.next; }
      //2
        head = deleteDuplicates(next);
      } else {
      //3
        head.next = deleteDuplicates(next);
      }
      return head;
      }
      }
    }

    解法6

    /**

     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode deleteDuplicates(ListNode head) {
            if (head == null || head.next == null) {return head;}
     
            ListNode dummy = new ListNode(0);
            dummy.next = head;
             
            ListNode p = head;
            ListNode q = dummy;
            boolean isDel = false;
             
            while(p != null){
                if(p.next != null && p.val == p.next.val ){
                    isDel = true;
                    p.next = p.next.next;
                }else{
                    p = p.next;
                    if(isDel){
                        q.next = p;
                        isDel = false;
                    }else{
                        q = q.next;
                    }
                }
            }
            return dummy.next;
        }
    }

    解法7: 

    原文链接:https://blog.csdn.net/weixin_43573824/article/details/88603222

    解题思路:

    1. 先虚拟一个头节点,这个头节点指向给定的头节点。
    2. 如果给定的头节点的值与下一个节点的值相等,就向后遍历,找到跟当前节点值不同的节点(temp)。
    3. 将虚拟头节点的下一个节点,指向temp。
    4. 以此思路往后遍历即可。

    public static ListNode deleteDuplicates(ListNode head) {
      if (head == null || head.next == null) return head;


      ListNode dummyHead = new ListNode(-1);
      dummyHead.next = head;
      ListNode first = dummyHead;
      while (head != null && head.next != null) {
        if (head.val == head.next.val) {
          int value = head.val;
          while (head != null && head.val == value) {
            head = head.next;
          }
          first.next = head;
        }else {
          first = head;
          head = head.next;
        }
      }
      return dummyHead.next;
    }

  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/long2050/p/12334082.html
Copyright © 2020-2023  润新知