package com.ttaylorr.ctci.answers.linked_lists;

import com.ttaylorr.ctci.answers.linked_lists.util.LinkedList;
import com.ttaylorr.ctci.meta.Solution;

import java.util.HashSet;
import java.util.Set;

@Solution(chapter = 2, problem = 1)
public class UnsortedDuplicateRemover<E> {
    protected final LinkedList.Node<E> head;

    public UnsortedDuplicateRemover(LinkedList.Node<E> head) {
        this.head = head;
    }

    public void removeWithBuffer() {
        if (this.head == null) return;

        Set<LinkedList.Node<E>> set = new HashSet<>();

        LinkedList.Node current = this.head;
        set.add(current);

        while ((current = current.next()) != null) {
            if(set.contains(current)) {
                // Skip the next element if it's already been found in the list
                current.next(current.next());
            } else {
                set.add(current);
            }
        }
    }

    public void removeWithoutBuffer() {
        if (this.head == null) return;

        // Keep track of the current and previous node (we'll remember the previous one
        // so that we can create a link to the next one if need-be.
        LinkedList.Node<E> previous = this.head;
        LinkedList.Node<E> current = previous.next();

        // Keep advancing until we hit the end of the list
        while (current != null) {
            // Create a runner which will loop through the head of the list up through the current
            // element and check for duplicates.
            LinkedList.Node<E> runner = this.head;
            while (runner != current) {
                // If we have a match (i.e., a duplicate) then create a link
                // over the duplicated element, and move on with our search.
                if (runner.data() == current.data()) {
                    LinkedList.Node<E> temp = current.next();
                    previous.next(temp);
                    current = temp;

                    // We can break here because we will only find at max one duplicate
                    // per element that we visit.
                    break;
                }
            }

            // If we haven't updated our pointer, do so now.
            if (runner == current) {
                previous = current;
                current = current.next();
            }
        }
    }
}


@@ -408,32 +408,386 @@
  = head;%0A    %7D%0A%0A
+    /**%0A     * This mutates and removes all duplicate nodes that are in the%0A     * same %7B@link com.ttaylorr.ctci.answers.linked_lists.util.LinkedList%7D as%0A     * the %60head%60 node.%0A     *%0A     * Since we use an extra buffer here, you'd prefer to use this implementation%0A     * when we're using a large linked list, since the amortized time is O(n).%0A     */%0A
     public void 
@@ -1276,24 +1276,346 @@
    %7D%0A    %7D%0A%0A
+    /**%0A     * %22This mutates and removes all duplicate nodes in the LinkedList, much the same as the%0A     * %60removeWithBuffer%60 method.%0A     *%0A     * Since we are using no buffer, you'd prefer to use this method over the other one when%0A     * the LinkedList is relatively small, since its amortized time is O(n%5E2).%0A     */%0A
     public v

Add some notes about which method one should prefer to use