3
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]

It does not eliminate the duplicates.

Why doesn't the method work?

4
  • stackoverflow.com/questions/9459557/… Commented Jul 14, 2013 at 21:11
  • You are not at all returning the new list from the deleteDups method. Commented Jul 14, 2013 at 21:11
  • 6
    I suggest you use your debugger in your IDE to step through the code and understand it. If you don't know how to use it, it's never too late to learn. I would also not use Hashtable as it is a legacy class for the last 15 years or so. You should use a set like HashSet. Commented Jul 14, 2013 at 21:11
  • Your list is not connected. You're just adding nodes but your function will return right away because each element does not have a "next" pointer set Commented Jul 14, 2013 at 21:32

19 Answers 19

11

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.

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;
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Why did you use HashMap instead of HashSet? The value of the key is unnecessary here. Though HashSet is backed by HashMap but it makes no sense to use which is not required by the design.
The appropriate data structure to be used here is a HashSet and not a map and certainly not a map that's thread-safe.
What is previous being used for here? Why will something like below not work? ~~~ public static void deleteDups (LinkedListNode n){ HashSet<Integer> set = new HashSet<Integer>(); while(n!=null){ if(set.containsKey(n.data)){ n=n.next } else { table.put(n.data, true); n=n.next; } } } ~~~
6
  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.
  3. The code below runs in O(1) space but O(N square) time.

    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

5 Comments

Maxime : Care to upvote if you think the solution is correct ? :)
It is not the optimal solution, that's why is not the correct answer.
I never argued that my solution is optimal (already explained in the solution). Just because solution is not optimal doesn't mean solution is not correct.
This same solution is given in Cracking the coding interview
Rambo7, I think your solution won't work if the duplicate is the last element of the list where runner.next!=null check will fail. I didn't test it, but try something like this: //0 1 2 3 4 1
3

Here's two ways of doing this in java. the method used above works in O(n) but requires additional space. Where as the second version runs in O(n^2) but requires no additional space.

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

Comments

2

You can use the following java method to remove duplicates:

1) With 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();
    }
}

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

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

2)With complexity of O(n) using hash table.

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=>

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

Comments

1

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

Comments

1

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

    }
}

2 Comments

i think the user here is expecting to write your own implementation of linkedlist and then remove duplicates and not just use the LinkedList class in the JAVA API to remove duplicates
Apart from using the JAVA API, adding the list to set will sort the elements. This contradicts to the problem statement of handling the UNSORTED list.
1
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;
         }
      }

}

Comments

1

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?

Comments

0

The first problem is that

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

does not actually initialize head with the contents of list. list.getFirst() simply returns the Integer 1, and head contains 1 as its only element. You would have to initialize head by looping through list in order to get all of the elements.

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. Therefore, to check your method, you would have to loop down head and print out each element, rather than printing out list again.

Comments

0

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

    }
}

Comments

0

here are a couple other solutions (slightly different from Cracking coding inerview, easier to read 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;
}

}

Comments

0

It's simple way without HashSet or creation Node.

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(" ", ""));
}

Comments

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

                    }
                }

            }

        }
    }

Comments

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

Comments

0

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)

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

Comments

0

All the solutions given above looks optimised but most of them defines custom Node as a part of solution. Here is a simple and practical solution using Java's LinkedList and HashSet which does not confine to use the preexisting libraries and methods.

Time Complexity : O(n)

Space Complexity: 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.

Comments

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

}

Comments

0

This is my Java version

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

Comments

-1

1.Fully Dynamic Approach 2.Remove Duplicates from LinkedList 3.LinkedList Dynamic Object based creation Thank you

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.