简体   繁体   English

从未排序的链表中删除重复项

[英]Remove duplicates from an unsorted linked list

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

The result: [1, 2, 3, 3, 3, 4, 4] [1, 2, 3, 3, 3, 4, 4]结果: [1, 2, 3, 3, 3, 4, 4] [1, 2, 3, 3, 3, 4, 4]

It does not eliminate the duplicates.它不会消除重复项。

Why doesn't the method work?为什么方法不起作用?

Iterate through the linked list, adding each element to a hash table.遍历链表,将每个元素添加到哈希表中。 When we discover a duplicate element, we remove the element and continue iterating.当我们发现重复元素时,我们删除该元素并继续迭代。 We can do this all in one pass since we are using a linked list.由于我们使用的是链表,因此我们可以一次性完成所有这些操作。

The following solution takes O(n) time, n is the number of element in the linked list.下面的解决方案需要 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;
  }
}
  1. The solution you have provided does not modify the original list.您提供的解决方案不会修改原始列表。
  2. To modify the original list and remove duplicates, we can iterate with two pointers.要修改原始列表并删除重复项,我们可以使用两个指针进行迭代。 Current: which iterates through LinkedList, and runner which checks all subsequent nodes for duplicates. Current: 遍历 LinkedList,运行程序检查所有后续节点是否有重复项。
  3. The code below runs in O(1) space but O(N square) time.下面的代码运行在 O(1) 空间但 O(N 平方) 时间。

    public void deleteDups(LinkedListNode head){ 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; }

    } }

Reference : Gayle laakmann mcdowell参考 : Gayle laakmann mcdowell

Here's two ways of doing this in java.这是在java中执行此操作的两种方法。 the method used above works in O(n) but requires additional space.上面使用的方法在 O(n) 中有效,但需要额外的空间。 Where as the second version runs in O(n^2) but requires no additional space.第二个版本在 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;
    }
}
}

You can use the following java method to remove duplicates:您可以使用以下 java 方法删除重复项:

1) With complexity of O(n^2) 1) complexityO(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();
    }
}

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

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

2 )With complexity of O(n) using hash table . 2 ) 使用哈希表的complexityO(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());

        }
    }

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

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

Ans is in C . Ans 在 C 中。 first sorted link list sort() in nlog time and then deleted duplicate del_dip() .首先在 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);
} 

Try this it is working for delete the duplicate elements from your 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);

    }
}

Here is a very easy version.这是一个非常简单的版本。

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

Very concise.非常简洁。 Isn't it?不是吗?

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

} }

The first problem is that第一个问题是

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

does not actually initialize head with the contents of list .实际上并不使用list的内容初始化head list.getFirst() simply returns the Integer 1 , and head contains 1 as its only element. list.getFirst()只返回整数1head包含1作为其唯一元素。 You would have to initialize head by looping through list in order to get all of the elements.您必须通过循环遍历list来初始化head以获取所有元素。

In addition, although此外,虽然

Task.deleteDups(head)

modifies head , this leaves list completely unchanged—there is no reason why the changes to head should propagate to list .修改head ,这使list完全不变——没有理由将head的更改传播到list Therefore, to check your method, you would have to loop down head and print out each element, rather than printing out list again.因此,要检查您的方法,您必须循环打印head并打印出每个元素,而不是再次打印出list

Try This.Its working.试试这个。它的工作。 // Removing Duplicates in Linked List // 去除链表中的重复项

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();

    }
}

here are a couple other solutions (slightly different from Cracking coding inerview, easier to read IMO).这里有一些其他解决方案(与 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;
}

} }

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

It's simple way without HashSet or creation Node.这是没有 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());
}

And to verify it:并验证它:

@Test
public void verifyThatNoDuplicatesInLinkedList(){
    CodeDataStructures dataStructures = new CodeDataStructures();

    assertEquals("abcdefghjk", dataStructures.removeDuplicates("abcdefgabcdeaaaaaaaaafabcdeabcdefgabcdbbbbbbefabcdefghjkabcdefghjkghjkhjkabcdefghabcdefghjkjfghjkabcdefghjkghjkhjkabcdefghabcdefghjkj")
            .replace(",", "")
            .replace("]", "")
            .replace("[", "")
            .replace(" ", ""));
}
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;
                        }

                    }
                }

            }

        }
    }

Below code implements this without needing any temporary buffer.下面的代码在不需要任何临时缓冲区的情况下实现了这一点。 It starts with comparing first and second nodes, if not a match, it adds char at first node to second node then proceeds comparing all chars in second node to char at third node and so on.它首先比较第一个和第二个节点,如果不匹配,则将第一个节点的字符添加到第二个节点,然后继续将第二个节点中的所有字符与第三个节点的字符进行比较,依此类推。 After comperison is complete, before leaving the node it clears everything that is added and restores its old value which resides at node.val.char(0) comperison 完成后,在离开节点之前,它会清除添加的所有内容并恢复其位于 node.val.char(0) 的旧值

F > FO > FOL > (match found, node.next = node.next.next) > (again match, discard it) > FOLW > .... 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;
        }
    }

All the solutions given above looks optimised but most of them defines custom Node as a part of solution.上面给出的所有解决方案看起来都经过优化,但其中大多数都将自定义Node定义为解决方案的一部分。 Here is a simple and practical solution using Java's LinkedList and HashSet which does not confine to use the preexisting libraries and methods.这是一个使用 Java 的LinkedListHashSet的简单实用的解决方案,它不限制使用预先存在的库和方法。

Time Complexity : O(n)时间复杂度:O(n)

Space Complexity: 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;
}

This also preserves the list order.这也保留了列表顺序。

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

}

This is my Java version这是我的 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();
        }
    }

1. Fully Dynamic Approach 2. Remove Duplicates from LinkedList 3. LinkedList Dynamic Object based creation Thank you 1.完全动态方法2.从 LinkedList 中删除重复项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);  
    }
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM