【问题标题】:Remove duplicates from an unsorted linked list从未排序的链表中删除重复项
【发布时间】:2013-07-12 16:48:57
【问题描述】:
import java.util.*;
/*
 *  Remove duplicates from an unsorted linked list
 */
public class LinkedListNode {  
    public int data;  
    public LinkedListNode next;  

    public LinkedListNode(int data) {  
        this.data = data;    
    }  
}

public class Task {
    public static void deleteDups(LinkedListNode head){
      Hashtable<Integer, Boolean> table=new Hashtable<Integer, Boolean>();
      LinkedListNode previous=null;
      //nth node is not null
      while(head!=null){
        //have duplicate
            if(table.containsKey(head.data)){
                            //skip duplicate
                previous.next=head.next;
            }else{
            //put the element into hashtable
            table.put(head.data,true);
            //move to the next element
            previous=head;
            }
      //iterate
      head=head.next;
      }
   }
   public static void main (String args[]){
       LinkedList<Integer> list=new LinkedList<Integer>();
       list.addLast(1);
       list.addLast(2);
       list.addLast(3);
       list.addLast(3);
       list.addLast(3);
       list.addLast(4);
       list.addLast(4);
       System.out.println(list);
       LinkedListNode head=new LinkedListNode(list.getFirst());
       Task.deleteDups(head);
       System.out.println(list);
   }
}

结果:[1, 2, 3, 3, 3, 4, 4] [1、2、3、3、3、4、4]

它不会消除重复。

为什么方法不起作用?

【问题讨论】:

  • 您根本没有从deleteDups 方法返回新列表。
  • 我建议您使用 IDE 中的调试器来单步调试代码并理解它。如果您不知道如何使用它,那么学习永远不会太晚。我也不会使用 Hashtable,因为它是过去 15 年左右的遗留类。您应该使用像 HashSet 这样的集合。
  • 您的列表未连接。您只是在添加节点,但您的函数将立即返回,因为每个元素都没有设置“下一个”指针

标签: java duplicates singly-linked-list


【解决方案1】:

遍历链表, 将每个元素添加到哈希表中。当我们发现重复元素时,我们删除该元素并继续迭代。由于我们使用的是链表,因此我们可以一次性完成所有操作。

下面的解需要O(n)时间,n是链表中元素的个数。

public static void deleteDups (LinkedListNode n){
  Hashtable table = new Hashtable();
  LinkedListNode previous = null;
  while(n!=null){
      if(table.containsKey(n.data)){
          previous.next = n.next;
      } else {
          table.put(n.data, true);
          previous = n;
      }
      n = n.next;
  }
}

【讨论】:

  • 为什么使用HashMap而不是HashSet?键的值在这里是不必要的。虽然 HashSet 有 HashMap 做后盾,但是设计上没有要求,使用起来毫无意义。
  • 此处使用的适当数据结构是 HashSet 而不是映射,当然也不是线程安全的映射。
  • previous 在这里是做什么用的?为什么像下面这样的东西不起作用? ~~~ public static void deleteDups (LinkedListNode n){ HashSet set = new HashSet(); while(n!=null){ if(set.containsKey(n.data)){ n=n.next } else { table.put(n.data, true); n=n.下一个; } } } ~~~
【解决方案2】:
  1. 您提供的解决方案并未修改原始列表。
  2. 要修改原始列表并删除重复项,我们可以使用两个指针进行迭代。 Current:遍历 LinkedList,运行器检查所有后续节点是否有重复。
  3. 下面的代码在 O(1) 空间中运行,但在 O(N 平方) 时间中运行。

    public void deleteDups(LinkedListNode head){

    if(head == null)
        return;
    
    LinkedListNode currentNode = head;       
    while(currentNode!=null){
        LinkedListNode runner = currentNode;
        while(runner.next!=null){
            if(runner.next.data == currentNode.data)
                runner.next = runner.next.next;
            else
                runner = runner.next;
        }
        currentNode = currentNode.next;
    }
    

    }

参考:Gayle laakmann mcdowell

【讨论】:

  • Maxime:如果您认为解决方案是正确的,是否愿意投票? :)
  • 不是最优解,所以不是正确答案。
  • 我从未争辩说我的解决方案是最优的(已经在解决方案中解释过)。解决方案不是最优的并不意味着解决方案不正确。
  • 破解编码面试中给出了相同的解决方案
  • Rambo7,如果重复项是 runner.next!=null 检查将失败的列表的最后一个元素,我认为您的解决方案将不起作用。我没有测试它,但尝试这样的事情: //0 1 2 3 4 1
【解决方案3】:

这里有两种在 java 中执行此操作的方法。上面使用的方法在 O(n) 中有效,但需要额外的空间。第二个版本在 O(n^2) 中运行,但不需要额外的空间。

import java.util.Hashtable;

public class LinkedList {
LinkedListNode head;

public static void main(String args[]){
    LinkedList list = new LinkedList();
    list.addNode(1);
    list.addNode(1);
    list.addNode(1);
    list.addNode(2);
    list.addNode(3);
    list.addNode(2);

    list.print();
    list.deleteDupsNoStorage(list.head);
    System.out.println();
    list.print();
}

public void print(){
    LinkedListNode n = head;
    while(n!=null){
        System.out.print(n.data +" ");
        n = n.next;
    }
}

public void deleteDups(LinkedListNode n){
    Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
    LinkedListNode prev = null;

    while(n !=null){
        if(table.containsKey(new Integer(n.data))){
            prev.next = n.next;     //skip the previously stored references next node
        }else{
            table.put(new Integer(n.data) , true);
            prev = n;       //stores a reference to n
        }

        n = n.next;
    }
}

public void deleteDupsNoStorage(LinkedListNode n){
    LinkedListNode current = n;

    while(current!=null){
        LinkedListNode runner = current;
        while(runner.next!=null){
            if(runner.next.data == current.data){
                runner.next = runner.next.next;
            }else{
                runner = runner.next;
            }
        }
        current = current.next;
    }

}

public void addNode(int d){
    LinkedListNode n = new LinkedListNode(d);
    if(this.head==null){
        this.head = n;
    }else{
        n.next = head;
        head = n;
    }
}

private class LinkedListNode{
    LinkedListNode next;
    int data;

    public LinkedListNode(int d){
        this.data = d;
    }
}
}

【讨论】:

    【解决方案4】:

    您可以使用以下java方法删除重复项:

    1) 与complexity of O(n^2)

    public void removeDuplicate(Node head) {
        Node temp = head;
        Node duplicate = null;                //will point to duplicate node
        Node prev = null;                     //prev node to duplicate node
        while (temp != null) {                //iterate through all nodes       
            Node curr = temp;
            while (curr != null) {                     //compare each one by one
                /*in case of duplicate skip the node by using prev node*/
                if (curr.getData() == temp.getData() && temp != curr) {        
                    duplicate = curr;
                    prev.setNext(duplicate.getNext());
                }
                prev = curr;
                curr = curr.getNext();
            }
            temp = temp.getNext();
        }
    }
    

    输入:1=>2=>3=>5=>5=>1=>3=>

    输出:1=>2=>3=>5=>

    2)与complexity of O(n) 使用哈希表。

    public void removeDuplicateUsingMap(Node head) {
        Node temp = head;
        Map<Integer, Boolean> hash_map = new HashMap<Integer, Boolean>(); //create a hash map
        while (temp != null) {  
            if (hash_map.get(temp.getData()) == null) {  //if key is not set then set is false
                hash_map.put(temp.getData(), false);
            } else {                                   //if key is already there,then delete the node
                deleteNode(temp,head);
            }
            temp = temp.getNext();
        }
    
    }
    
    public void deleteNode(Node n, Node start) {
            Node temp = start;
            if (n == start) {
                start = null;
            } else {
                while (temp.getNext() != n) {
                    temp = temp.getNext();
                }
    
                temp.setNext(n.getNext());
    
            }
        }
    

    输入:1=>2=>3=>5=>5=>1=>3=>

    输出:1=>2=>3=>5=>

    【讨论】:

      【解决方案5】:

      Ans 在 C 中。先在nlog时间内对链表sort()进行排序,然后删除重复的del_dip()。

      node * partition(node *start)
      {
          node *l1=start;
          node *temp1=NULL;
          node *temp2=NULL;
          if(start->next==NULL)
              return start;
      
          node * l2=f_b_split(start);
            if(l1->next!=NULL)
              temp1=partition(l1);
            if(l2->next!=NULL)
                  temp2=partition(l2);
      
      if(temp1==NULL || temp2==NULL)
          {
              if(temp1==NULL && temp2==NULL)
              temp1=s_m(l1,l2);
      
              else if(temp1==NULL)
              temp1=s_m(l1,temp2);
      
              else if(temp2==NULL)
              temp1=s_m(temp1,l2);
      }
          else
                  temp1=s_m(temp1,temp2);
      
          return temp1;
      }
      
      node * sort(node * start)
      {
          node * temp=partition(start);
              return temp;
      }
      
      void del_dup(node * start)
      {
        node * temp;
          start=sort(start);
          while(start!=NULL)
              {
              if(start->next!=NULL && start->data==start->next->data  )
                  {
                      temp=start->next;
                      start->next=start->next->next;
                      free(temp);
                  continue;
                  }
              start=start->next;
              }
      }
      
      void main()
       {
          del_dup(list1);
          print(list1);
      } 
      

      【讨论】:

        【解决方案6】:

        试试这个,它可以从你的linkedList中删除重复的元素

        package com.loknath.lab;
        
        import java.util.ArrayList;
        import java.util.HashSet;
        import java.util.LinkedList;
        import java.util.Set;
        
        public class Task {
            public static void main(String[] args) {
        
                LinkedList<Integer> list = new LinkedList<Integer>();
                list.addLast(1);
                list.addLast(2);
                list.addLast(3);
                list.addLast(3);
                list.addLast(3);
                list.addLast(4);
                list.addLast(4);
                deleteDups(list);
                System.out.println(list);
            }
        
            public static void deleteDups(LinkedList<Integer> list) {
                Set s = new HashSet<Integer>();
                s.addAll(list);
                list.clear();
                list.addAll(s);
        
            }
        }
        

        【讨论】:

        • 我认为这里的用户希望编写自己的链表实现,然后删除重复项,而不仅仅是使用 JAVA API 中的 LinkedList 类来删除重复项
        • 除了使用 JAVA API 之外,将列表添加到 set 将对元素进行排序。这与处理 UNSORTED 列表的问题陈述相矛盾。
        【解决方案7】:
        I think you can just use one iterator current to finish this problem 
        
        public void compress(){
            ListNode current = front;
            HashSet<Integer> set = new HashSet<Integer>();
            set.add(current.data);
            while(current.next != null){
               if(set.contains(current.next.data)){
                  current.next = current.next.next;         }
                 else{
                    set.add(current.next.data);
                    current = current.next;
                 }
              }
        

        }

        【讨论】:

          【解决方案8】:

          这是一个非常简单的版本。

          LinkedList<Integer> a = new LinkedList<Integer>(){{
            add(1);
            add(1);
          }}
          Set<Integer> set = new HashSet<Integer>(a);
          a = new LinkedList<Integer>(set);
          

          非常简洁。不是吗?

          【讨论】:

            【解决方案9】:

            第一个问题是

            LinkedListNode head=new LinkedListNode(list.getFirst());
            

            实际上并没有用list 的内容初始化head。 list.getFirst() 只返回整数 1,head 包含 1 作为其唯一元素。您必须通过循环 list 来初始化 head 才能获取所有元素。

            另外,虽然

            Task.deleteDups(head)
            

            修改head,这使list 完全保持不变——head 的更改没有理由传播到list。因此,要检查您的方法,您必须循环使用head 并打印出每个元素,而不是再次打印出list。

            【讨论】:

              【解决方案10】:

              试试这个。它的工作原理。 // 删除链表中的重复项

              import java.io.*;
              import java.util.*;
              import java.text.*;
              class LinkedListNode{
                  int data;
                  LinkedListNode next=null;
              
                  public LinkedListNode(int d){
                      data=d;
                  }
                  void appendToTail(int d){
                      LinkedListNode newnode = new LinkedListNode(d);
                      LinkedListNode n=this;
                      while(n.next!=null){
                          n=n.next;
                      }
                      n.next=newnode;
                  }
              
                  void print(){
                      LinkedListNode n=this;
                      System.out.print("Linked List: ");
                      while(n.next!=null){
                          System.out.print(n.data+" -> ");
                          n=n.next;
                      }
                      System.out.println(n.data);
                  }
              }
              class LinkedList2_0
              {
                  public static void deletenode2(LinkedListNode head,int d){
                      LinkedListNode n=head;
                      // If It's head node
                      if(n.data==d){
                          head=n.next;
                      }
                      //If its other
                      while(n.next!=null){
                          if(n.next.data==d){
                              n.next=n.next.next;
                          }
                          n=n.next;
                      }
                  }
              
                  public static void removeDuplicateWithBuffer(LinkedListNode head){
                      LinkedListNode n=head;
                      LinkedListNode prev=null;
                      Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();
                      while(n!=null){
                          if(table.containsKey(n.data)){
                              prev.next=n.next;
                          }
                          else{
                              table.put(n.data,true);
                              prev=n;
                          }
                          n=n.next;
                      }
                  }
                  public static void removeDuplicateWithoutBuffer(LinkedListNode head){
                      LinkedListNode currentNode=head;
                      while(currentNode!=null){
                          LinkedListNode runner=currentNode;
                          while(runner.next!=null){
                              if(runner.next.data==currentNode.data){
                                  runner.next=runner.next.next;
                              }
                              else
                                  runner=runner.next;
                          }
                          currentNode=currentNode.next;
                      }
                  }
                  public static void main(String[] args) throws java.lang.Exception {
                      LinkedListNode head=new LinkedListNode(1);
                      head.appendToTail(1);
                      head.appendToTail(3);
                      head.appendToTail(2);
                      head.appendToTail(3);
                      head.appendToTail(4);
                      head.appendToTail(5);
                      head.print();
              
                      System.out.print("After Delete: ");
                      deletenode2(head,4);
                      head.print();
              
                      //System.out.print("After Removing Duplicates(with buffer): ");
                      //removeDuplicateWithBuffer(head);
                      //head.print();
              
                      System.out.print("After Removing Duplicates(Without buffer): ");
                      removeDuplicateWithoutBuffer(head);
                      head.print();
              
                  }
              }
              

              【讨论】:

                【解决方案11】:

                这里有几个其他解决方案(与 Cracking coding inerview 略有不同,更易于阅读 IMO)。

                public void deleteDupes(Node head) {
                
                Node current = head;
                while (current != null) {
                    Node next = current.next;
                    while (next != null) {
                        if (current.data == next.data) {
                            current.next = next.next;
                            break;
                        }
                
                        next = next.next;
                    }
                
                    current = current.next;
                }
                

                }

                public void deleteDupes(Node head) {
                Node current = head;
                while (current != null) {
                    Node next = current.next;
                    while (next != null) {
                        if (current.data == next.data) {
                            current.next = next.next;
                            current = current.next;
                            next = current.next;
                        } else {
                            next = next.next;
                        }
                    }
                
                    current = current.next;
                }
                

                }

                【讨论】:

                  【解决方案12】:

                  没有HashSet或创建节点的简单方法。

                  public String removeDuplicates(String str) {
                      LinkedList<Character> chars = new LinkedList<Character>();
                  
                      for(Character c: str.toCharArray()){
                          chars.add(c);
                      }
                  
                      for (int i = 0; i < chars.size(); i++){
                          for (int j = i+1; j < chars.size(); j++){
                              if(chars.get(j) == chars.get(i)){
                                  chars.remove(j);
                                  j--;
                              }
                          }
                      }
                  
                      return new String(chars.toString());
                  }
                  

                  并验证它:

                  @Test
                  public void verifyThatNoDuplicatesInLinkedList(){
                      CodeDataStructures dataStructures = new CodeDataStructures();
                  
                      assertEquals("abcdefghjk", dataStructures.removeDuplicates("abcdefgabcdeaaaaaaaaafabcdeabcdefgabcdbbbbbbefabcdefghjkabcdefghjkghjkhjkabcdefghabcdefghjkjfghjkabcdefghjkghjkhjkabcdefghabcdefghjkj")
                              .replace(",", "")
                              .replace("]", "")
                              .replace("[", "")
                              .replace(" ", ""));
                  }
                  

                  【讨论】:

                    【解决方案13】:
                    LinkedList<Node> list = new LinkedList<Node>();
                    
                     for(int i=0; i<list.size(); i++){
                            for(int j=0; j<list.size(); j++){
                                if(list.get(i).data == list.get(j).data && i!=j){
                                    if(i<j){
                                         list.remove(j);
                                        if(list.get(j)!= null){
                                             list.get(j-1).next = list.get(j);
                                        }else{
                                            list.get(j-1).next = null;
                                        }
                    
                                    }
                                    else{
                                        if(i>j){
                                            list.remove(i);
                                            if(list.get(i) != null){
                                                list.get(j).next = list.get(i);
                                            }else{
                                                list.get(j).next = null;
                                            }
                    
                                        }
                                    }
                    
                                }
                    
                            }
                        }
                    

                    【讨论】:

                      【解决方案14】:
                      /**
                      *
                      * Remove duplicates from an unsorted linked list.
                      */
                      public class RemoveDuplicates {
                          public static void main(String[] args) {
                              LinkedList<String> list = new LinkedList<String>();
                              list.add("Apple");
                              list.add("Grape");
                              list.add("Apple");
                              HashSet<String> set = removeDuplicatesFromList(list);
                              System.out.println("Removed duplicates" + set);
                          }
                          public static HashSet<String> removeDuplicatesFromList(LinkedList<String> list){
                              HashSet<String> set = new LinkedHashSet<String>();
                              set.addAll(list);
                              return set;
                          }
                      }
                      

                      【讨论】:

                        【解决方案15】:

                        下面的代码实现了这一点,不需要任何临时缓冲区。它首先比较第一个和第二个节点,如果不匹配,它将第一个节点的字符添加到第二个节点,然后继续将第二个节点中的所有字符与第三个节点的字符进行比较,依此类推。完成后,在离开节点之前,它会清除添加的所有内容并恢复其位于 node.val.char(0) 的旧值

                        F > FO > FOL > (找到匹配,node.next = node.next.next) > (再次匹配,丢弃) > FOLW > ....

                        public void onlyUnique(){
                                Node node = first;
                                while(node.next != null){
                                    for(int i = 0 ; i < node.val.length(); i++){
                                        if(node.val.charAt(i) == node.next.val.charAt(0)){
                                            node.next = node.next.next;
                                        }else{
                                            if(node.next.next != null){ //no need to copy everything to the last element
                                                node.next.val = node.next.val + node.val;
                                            }
                                            node.val = node.val.charAt(0)+ "";
                                        }
                                    }
                                    node = node.next;
                                }
                            }
                        

                        【讨论】:

                          【解决方案16】:

                          上面给出的所有解决方案看起来都经过优化,但大多数都将自定义 Node 定义为解决方案的一部分。这是一个使用 Java 的 LinkedList 和 HashSet 的简单实用的解决方案,它不限于使用预先存在的库和方法。

                          时间复杂度:O(n)

                          空间复杂度:O(n)

                          @SuppressWarnings({ "unchecked", "rawtypes" })
                          private static LinkedList<?> removeDupsUsingHashSet(LinkedList<?> list) {
                          
                              HashSet set = new HashSet<>();
                              for (int i = 0; i < list.size();) {
                                  if (set.contains(list.get(i))) {
                                      list.remove(i);
                                      continue;
                                  } else {
                                      set.add(list.get(i));
                                      i++;
                                  }
                              }
                              return list;
                          }
                          

                          这也保留了列表顺序。

                          【讨论】:

                            【解决方案17】:
                            public static void main(String[] args) {
                            
                                LinkedList<Integer> linkedList = new LinkedList<>();
                                linkedList.add(1);
                                linkedList.add(2);
                                linkedList.add(2);
                                linkedList.add(3);
                                linkedList.add(4);
                                linkedList.add(5);
                                linkedList.add(6);
                                deleteElement(linkedList);
                                System.out.println(linkedList);
                            }
                            
                            private static void deleteElement(LinkedList<Integer> linkedList) {
                            
                                Set s = new HashSet<Integer>();
                            
                                s.addAll(linkedList);
                                linkedList.clear();
                                linkedList.addAll(s);
                            
                            }
                            

                            【讨论】:

                              【解决方案18】:

                              这是我的 Java 版本

                              //  Remove duplicate from a sorted linked list
                              public void removeDuplicates() {
                              
                                      Node current = head;
                                      Node next = null;
                                      /* Traverse list till the last node */
                                      while (current != null) {
                                          next = current;
                              
                                          /*
                                           * Compare current node with the next node and keep on deleting them until it
                                           * matches the current node data
                                           */
                                          while (next != null && current.getValue() == next.getValue()) {
                              
                                              next = next.getNext();
                              
                                          }
                              
                                          /*
                                           * Set current node next to the next different element denoted by temp
                                           */
                                          current.setNext(next);
                                          current = current.getNext();
                                      }
                                  }
                              

                              【讨论】:

                                【解决方案19】:

                                1.完全动态的方法 2.从链表中删除重复项 3.基于LinkedList动态对象的创建 谢谢

                                import java.util.Scanner;
                                class Node{
                                    int data;
                                    Node next;
                                    public Node(int data)
                                    {
                                        this.data=data;
                                        this.next=null;
                                    }
                                }
                                class Solution
                                {
                                    public static Node insert(Node head,int data)
                                    {
                                    Node p=new Node(data);
                                    if(head==null)
                                    {
                                        head=p;
                                    }
                                    else if(head.next==null)
                                    {
                                        head.next=p;
                                    }
                                    else
                                    {
                                        Node start=head;
                                        while(start.next!=null)
                                        {
                                            start=start.next;   
                                        }
                                        start.next=p;
                                        return head;
                                        //System.out.println();
                                    }
                                    return head;    
                                    }
                                    public static void display(Node head)
                                    {
                                        Node start=head;
                                        while(start!=null)
                                        {
                                            System.out.print(start.data+" ");
                                            start=start.next;
                                        }
                                
                                    }
                                    public static Node remove_duplicates(Node head)
                                    {
                                       if(head==null||head.next==null)
                                       {
                                           return head;
                                       }
                                       Node prev=head;
                                       Node p=head.next;
                                
                                       while(p!=null)
                                       {
                                           if(p.data==prev.data)
                                           {
                                            prev.next=p.next;
                                            p=p.next;              
                                           }
                                           else{
                                               prev=p;
                                               p=p.next;   
                                           }
                                       }
                                       return head;
                                    }
                                    public static void main(String args[])
                                    {
                                        Scanner sc=new Scanner(System.in);
                                        Node head=null;
                                        int T=sc.nextInt();
                                        while(T-->0)
                                        {
                                            int ele=sc.nextInt();
                                            head=insert(head,ele);
                                        }
                                        head=remove_duplicates(head);
                                        display(head);  
                                    }
                                }
                                

                                输入: 5 1 1 2 3 3 输出: 1 2 3

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 2020-06-09
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2016-01-24
                                  • 1970-01-01
                                  • 2021-11-23
                                  • 2013-04-28
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多