简体   繁体   中英

Remove Duplicates from Linked List

So I have a linked list that I am trying to remove duplicates from.

My basic algorithm that I thought up is to pretty much use the runner technique. Where I keep two pointers to compare adjacent elements. If they are the same I change the pointer of p1 to point to p1.next.next if not I keep traversing the list. However I keep getting a null pointer exception in the solution I have typed.

Node RemoveDuplicates(Node head) {
  // This is a "method-only" submission. 
  // You only need to complete this method. 
    if (head == null){
        return null;
    } 

        Node current = head;
    Node runner = head;



    while(current != null && runner != null && runner.next != null){
    runner = runner.next;
    if(runner.data == current.data){
        if(current.next != null){
                    current = current.next.next; 

        }
    }else{
        current = current.next;
    }
}



    return current;
}

At the point that I exit the while loop current is null. Which I think is the problem. How would I return the head of the altered list.

OK, although you've already accepted an answer, here's some example code using recursion to remove the dups from an ordered list per your request in the comments. (if your list isn't ordered, order it :) )

public Node removeDups(Node root) {
    if (root.next == null)
        return root;
    root.next = removeDups(root.next);
    if (root.data == root.next.data)
        return root.next;
    return  root;
} // call as root = removeDups(root);

As you mentioned, recursion isn't really necessary here but you're using a Node-based linked list which is recursively defined. So, when it makes sense, the elegance of the solution has its benefits.

What I like about it is that you're not doing any node.next.next or needing to check for that null case. Once the stack starts unwinding, you're already in a position to start checking for dups. Then it's just a matter of comparing root.data and root.next.data ; both of which you already know exist.

You can do this with single traversal with 2 pointer.and also this code works with single while loop.

public Node deleteDuplicates(Node head) {
        Node current=head;
            if (head == null)
                return null;
            else
            {
             Node runner=head.next;
               while(head.next!=null && runner!=null)
                {
                    if(head.val == runner.val)
                       prev=runner.next;
                    else
                    {
                      head.next=runner;
                      head=head.next;
                      prev=runner.next;
                    }
                }
                head.next=runner;
            }
            return current; 
    }

First of all, you'll want to return head at the end, so that you are returning the list, not just the last element. Second thing, you'll want to modify the .next references instead of assigning them in some of the cases.

Note this doesn't work if the list isn't sorted.

Before: 1 1 3 3
After: 1 3

This code works (and I've tested it)

static Node RemoveDuplicates(Node head) {
    if (head == null) return null;

    Node current = head;
    Node runner = head;

    while (current != null && current.next != null) {
        runner = current.next;
        while (runner != null && runner.data == current.data) {
            current.next = runner.next; // skip the repeat
            runner = runner.next;
        }
        current = current.next;
    }
    return head;
}

You can do this in a single traversal. Just maintain two pointers temp and next_of_next. Make temp iterate for each node and when the data of temp and the next node is equal, point next_of_next to the alternate node after temp and delete the node after temp.

Node removeDuplicates(Node head)
{
    Node temp = head;
    Node next_of_next;
    if (head == null)    
        return;
    while (temp.next != null) 
    {
        if (temp.data == temp.next.data) 
        {
            next_of_next = temp.next.next;
            temp.next = null;
            temp.next = next_of_next;
        }
        else 
           temp = temp.next;
    }
return head ;
}

Here a solution without recursion using a HashSet :

public void RemoveDuplicates()
{
    if (head != null)
    {
        var hm = new HashSet<T>();
        Node current = head;
        Node prev = null;

        while (current != null)
        {
            if (!hm.Contains(current.Value))
            {
                hm.Add(current.Value);
                prev = current;
                current = current.Next;
            }
            else
            {
                prev.Next = current.Next;
                current = prev.Next;
            }
        }
    }
    return head;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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