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

引用:原文链接: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};
    //删除链表中的重复元素,保留一个
    ListNode head = new ListNode(arr);
    head = deleteDuplicates1(head);
    System.out.println(head.toString());
  }

  public ListNode deleteDuplicates(ListNode head) {
    //设置一个指向当前元素的指针
    ListNode current = head;
    //当链表为空或者链表中遍历到最后一个元素时,出循环
    while (current != null && current.next != null) {
      //如果找到当前节点和它的下一个结点的值相同,删除掉下一个结点
      if (current.next.val == current.val) {
        current.next = current.next.next;
      } else {
        //如果没有找到,当前节点后移
        current = current.next;
      }
    }
    return head;
  }


  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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章