Running Time and Memory Usage for Make Unique Function

public void makeUnique() {
	DynamicArray<T> existing = new DynamicArray<T>();
	
	for (DLLNode<T> value : this) {
		if (!existing.contains(value.data))
			existing.append(value.data);
		else
			deleteNode(value);
	}
}

Running Time

The above algorithm consists of two parts:

PartPurposeRuntime Cost
A[[Assignment 2#A Allocation of a new DynamicArray type|Allocation of a new DynamicArray type]]
B[[Assignment 2#B Iterating through the DoublyLinkedList|Iterating through the DoublyLinkedList]]

Since these parts are sequential, we can find the overall runtime cost as:

A: Allocation of a new DynamicArray type

As per it’s constructor:

public DynamicArray() {
	this.storage = (T[]) new Object[capacity];
}

It is clear that all it is responsible for is initialisation, hence,

B: Iterating through the DoublyLinkedList

As per the Iterable implementation on DoublyLinkedList:

@Override
public Iterator<DLLNode<T>> iterator() {
	return new Iterator<DLLNode<T>>() {
		/**
		 * The current node indexed by the iterator
		 */
		private DLLNode<T> current = head;
		
		/**
		 * @return if the next node in the list exists or not
		 */
		@Override
		public boolean hasNext() {
			return current != null;
		}
		
		/**
		 * @return the next node in the list
		 */
		@Override
		public DLLNode<T> next() {
			DLLNode<T> previous = current;
			current = current.next;
			return previous;
		}
	};
}

In the worse case the below loop is time, as it makes use of the above Iterator

for (DLLNode<T> value : this)

And in the worst case the contains check is also as there would be elements in the DynamicArray

if (!existing.contains(value.data))
public boolean contains(T value) {
	for (T existsInArray : this)
		if (value == existsInArray)
			return true;
		    
	return false;
}
@Override
public Iterator<T> iterator() {
	return new Iterator<T>() {
		int index = 0;
		
		/**
		* @return if the iterator can continue
		*/
		@Override
		public boolean hasNext() {
			return index < length;
		}
		      
		/**
		* @return the next value in storage
		*/
		@Override
		public T next() {
			return storage[index++];
		}
	};
 }

Hence, since the loop calls contains times in the worst case average time complexity for the loop.

Both DoublyLinkedList#deleteNode and DynamicArray#append can be considered to be constant time operations.

In conclusion by worst case asymptotic analysis, the makeUnique function runs in


Memory Usage

The algorithm uses the following memory:

Memory UserJustification
Doubly Linked ListThe list itself is not copied or cloned and is modified in place
Dynamic ArrayThe dynamic array may, in the worst case, contain all elements in the linked list, if every element is unique. Hence it could run with complexity in the worst case