Removing double Objects in Java List - java

For the exam, I train to write the some algorithms to the final exam. One of them is creating the reverse() method, which removes doubles in the List<> . The problem that the void method only removes one double or two. How can I change the method?
Here, the code of the List.java file. The methods removeFromBack(), removeFromFront(), insertAtBack(), insertAtFront(), print(), isEmpty(), the classes List and ListNode are already defined in Deitel's Java book. Additionally, all imports are done:
public void removeDuplicates() {
ArrayList<T> toCheck = new ArrayList<T>();
ListNode<T> current = firstNode;
while (current != null) {
toCheck.add(current.data);
current = current.nextNode;
}
current = firstNode;
HashSet<T> toCheck2 = new LinkedHashSet<T>();
for (T element: toCheck) {
toCheck2.add(element);
}
for (T element: toCheck2) {
removeFromBack();
insertAtBack(element);
}
}

you can add duplicates list and remove them like this:
public void removeDuplicates() {
ArrayList<T> elements = new ArrayList<T>();
ListNode<T> current = firstNode;
while (current != null) {
if(!elements.contains(current.data))
toCheck.add(current.data);
else {
// you have the duplicates, do your logic
}
current = current.nextNode;
}
}

There are faster/more efficient ways depending on your needs but this one should basically always work:
public static <T> ArrayList<T> removeDuplicates(ArrayList<T> toCheck) {
ArrayList<Integer> toRemove = new ArrayList<Integer>();
for(int i = 0; i < toCheck.size(); i++) {
T current = toCheck.get(i);
for(int j = 0; j < toCheck.size(); j++) {
if(j == i)continue;
if(toCheck.get(j) == current) {
toRemove.add(j);
}
}
}
Collections.sort(toRemove, Collections.reverseOrder());
for(int i : toRemove) {
toCheck.remove(i);
}
return toCheck;
}

For duplicates in List, you could always use Set to help to remove the duplicates:
public List<Integer> removeDuplicates(List<Integer> list) {
Set<Integer> set = new HashSet<>(list); // remove all duplicates in set
List<Integer> result = new ArrayList(set.size());
for (Integer i : list) {
if (set.contains(i)) {
result.add(i);
set.remove(i); // delete, so duplicate item will not be added to result twice
}
}
return result;
}

Related

How to create a linked list in java without importing linked lists

i am a CS student in college and i am having trouble with this project where i am supoosed to create a linked list using nodes without importing linked lists, as well as doing a some methods with the list. i am a beginner when it comes to coding, so assume i know nothing, because that is probably the case lol.
import java.io.*;
import java.lang.*;
public class List {
public int listCount = 0;
public char[] linkedList;
public List() throws FileNotFoundException {
}
public List(char[] array) throws FileNotFoundException {
if (array.length == 1) {
Node head = new Node(array[0]);
} else if (array.length > 1) {
Node head = new Node(array[0]);
Node traverse = head;
for (int i = 1; i < array.length; i++) {
while (traverse.nextNode != null) {
traverse = traverse.nextNode;
}
traverse.nextNode = new Node(array[i]);
listCount++;
}
}
}
public List(String w) throws FileNotFoundException {
char[] array2 = new char[w.length()];
for (int i = 0; i < w.length(); i++) {
array2[i] = w.charAt(i);
}
List str = new List(array2);
}
/* Find the character at a index
#param int index
return the character at the chosen index
*/
public char charAt(int index) throws IndexOutOfBoundsException {
char results = linkedList[0];
if (index < linkedList.length && index >= 0) {
results = linkedList[index];
}
return results;
}
public String concat(int index1, int index2) {
return null;
}
/* Determine if the list is empty
return whether the given conditions are true or false
*/
public boolean isEmpty() {
for (int i = 0; i < linkedList.length; i++) {
if (!linkedList.equals(null)) {
System.out.println("This list is not empty");
return false;
}
}
System.out.println("List is empty");
return true;
}
/* Determine the size of the list
return the size of the list
*/
public int size() {
return listCount;
}
/* Create a new String between 2 index's including the start and end index
#param beginIndex is the starting point of the new String
#endIndex is the ending point of new String
return the new String
*/
public String subString(int beginIndex, int endIndex) {
return null;
}
public void insert(Object x) throws IndexOutOfBoundsException {
if (listCount > 100 || listCount < 0) {
throw new IndexOutOfBoundsException("Bag is too large");
} else {
this.linkedList[listCount] = (char) x;
listCount++;
}
}
}
i appreciate any help or pointers ahead of time. we are using a separate node, helper, and driver class as well as a .txt file to assign into my list. i am stuck on the concat and substring methods too, but i want to make sure i am getting the framework correct first. thank you again.
If i understand your question correctly, you are asking how to access a specific type without importing it.
Imports are required to identify which type is referenced when it is used by its simple name. To reference a type without declaring it in the imports you need to use its fully qualified name. For instance
java.util.List<String> someList = new java.util.ArrayList<>();
works without importing List and ArrayList because by declaring the package the class is in it is clear which class is being referenced.
I'll try to do the code later, but here is a book that i found that may help you.
https://cin.ufpe.br/~grm/downloads/Data_Structures_and_Algorithms_in_Java.pdf
I bought a book about DATA STRUCTURE from Pearson company, and it's really a good book, but i don't remember much, it's something like this, that i did in a hurry:
public class List {
private Node head = null;
private Node foot = null;
private Node newNode = null;
private Node auxNode = null;
public List() {
this.head = new Node();
this.foot = new Node();
}
public class Node {
private int adress;
private Node nextNode;
}
public void add(int value) {
this.newNode = new Node();
newNode.adress = value;
if (head == null) {
// Head of the list receive the values of the NEW NODE, so the head of the list
// is not null enymore
head = newNode;
head.nextNode = null;
} else {
// In this case Head is not null
/*The auxiliary node will receive the head and the new Node will become the new Head from the list*/
auxNode = new Node();
auxNode = head;
/*
while(auxNode.nextNode != null ) {
}
auxNode = head;
//head of the list is empty, so we can add the new node
head = newNode;//Here the new node is empty because was transfered to the head
head.nextNode = auxNode; //The head of the list receive the old node that used to be the head
if (head.nextNode == null) {
head.nextNode = newNode;
} else if (head.nextNode != null) {
}*/
}
}
}
```
I hope this help you to get some lead

Removing element from array. Getting null instead of actually removing element/index

I'm trying to remove an element from an array. I am running into an issue where when I run my program and remove a certain index. I get nulls in the place where the element/index should be removed entirely.
My output is when I execute list.display() in the main method is
Tom, Bob, Richard
However after I execute list.remove() and run the program. I get
null, null, Richard.
Any tips?
public class MyArrayList implements MyList {
private Object[] theList;
public MyArrayList()
{
theList = new Object[0];
}
public boolean add(Object toAdd){
if(toAdd != null) {
Object[] temp = new Object[theList.length + 1];
for(int i = 0; i < theList.length; i++) {
temp[i] = theList[i];
}
temp[theList.length] = toAdd;
theList = temp;
return true;
} else {
return false;
}
}
public Object remove(int index) {
if (index >= 0 && index < theList.length) {
Object[] temp = new Object[theList.length - 1];
theList[index] = null;
int j = 0;
for (int i = 0; i < theList.length; i++) {
if (i == index) {
continue;
}
temp[j++] = theList[i];
theList = temp;
}
return temp;
}
return null;
}
public class Main {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add("Tom");
list.add("Bob");
list.add("Richard");
list.display();
list.remove(0);
list.remove(1);
list.display();
}
}
Where you call list.remove(0), you should be assigning the result back to list again. For example:
list = list.remove(0);
A couple of other things:
It's generally a bad idea to change the index variable within a loop. It's legal, but leads to logic errors that can be difficult to reason about and diagnose.
You're getting the null in your output because the remove method also mutates the theList when you execute:
theList[index] = null;
Since you're returning a copy of theList you don't need to also set that element of the theList array to null.
Since your code implements MyList which is not available in code, i could not run below sample on your code but you can have below logic in your code. You don't need extra temp array in remove method. Since it an array, you can start traversing array from index which has to be removed and start moving next element by one step before.
public Object remove(int index) {
if (theList == null || index < 0 || index >= theList.length) {
return theList;
}
for (int i = index; i < theList.length; i++) {
theList[i] = theList[i + 1];
}
return null;
}
You can trim array tail if it has more empty places based on some threshold.
the code is doing exactly what you asked it to do. Those removed values are null because you have this line
theList[index] = null;
Also think about what your intentions are.
list.remove(0); <- this will remove the first element so now list would be Rob, Richard
list.remove(1); <- this will remove the 2nd element of the modified list (Rob, Richard) so result would be Rob. This is probably not what you want.
instead of this
if (i == index) {
i++; // risk of out of bounds exception
}
you probably want this instead
if (i == index) {
continue;
}

Removes the first occurrence of every element that appears more than once in the linkedlist

Write the method removeFirst, member of class LinkedList, that removes the first occurrence of every element that appears more than once in the list. Do not use any auxiliary data structures and do not call any methods. The method signature is public void removeFirst().
Example 4.1. If the list contains: B => A => A => R => C => A => C => R, then
after calling removeFirst, its content becomes B => A => A => C => R.
I solved it as a member of class Arraylist and I used auxiliary data structures.
public void removeFirst() {
Node<T> traverse = head;
int[] array = new int[10];
int[] repeat = new int[10];
int count=0;
int rcount=0;
boolean isAlready = false;
while (traverse!=null)
{
for (int i=0; i<count; i++)
{
if (array[i]==traverse.value)
{
isAlready=true;
break;
}
}
if(!isAlready)
array[count++] = traverse.value;
else
repeat[rcount++] = traverse.value;
traverse = traverse.next;
}
traverse= head;
while (traverse!=null)
{
for (int i=0; i<rcount; i++)
traverse=traverse.next;
}
}//
any idea how this can be solved as member of likedlist class without using any auxiliary data structure and all you can use is the
public class Node<T> {
public T data;
public Node<T> next;
public Node () {
data = null;
next = null;
}
public Node (T val) {
data = val;
next = null;
}
// Setters/Getters...
}//End of class Node
public class LinkedList<T> { //LinkedList class
private Node<T> head;
private Node<T> current;
public LinkedList () {
head = current = null;
}
I come across this problem while I was studying for Data Structure Course it's kinda hard but here is what I did.
public void removeFirst() {
int counter = 0 ;
Node<T> tmp = null ;
Node<T> comp = head ;
current = head ;
Node<T> secHead = null ;
Node<T> secCurr = null ;
boolean check = false ;
boolean control = true ;
while(current.next != null || current == null) {
counter = 0 ;
comp = head ;
while(comp.next != null) { // we iterate using node through original list to check for occurences
if(comp.data == current.data) {
counter++;
}
comp = comp.next ;
}
if(comp.data == current.data) {
counter++;
}
tmp = current ;
if(counter >= 2) {
check = false ;
secCurr = secHead ;
while(secCurr != null) { // check for deleting to avoid multiple deletes
if(tmp.data.equals(secCurr.data)) {
check = true ;
break ;
}
secCurr = secCurr.next ;
}
secCurr = secHead ;
if(!check) { // deleting and adding to our secondary linkedlist to check it later :)
remove();
control = false ;
Node<T> tmp2;
if (secHead == null) {
secHead = new Node<T> (tmp.data);
secCurr = secHead ;
}
else {
tmp2 = secCurr.next;
secCurr.next = new Node<T> (tmp.data);
secCurr = secCurr.next;
secCurr.next = tmp2;
}
}
}
if(control) { // remove() increment the current this is for checking
current = current.next ;
}
control = true ;
}
}
by using the properties of class node you can make secondary LinkedList but not using the class itself hence we never used auxiliary data structure. you need to know how the internal methods work specifically. read the code carefully : )
I started by taking the elements in reverse order and saw if there were repeated elements on the right side and then checked from the left side.
The only case you need to delete is when the repeated elements are on the right side only.
At the end of the code, I made one case to check the head element.
public void removeFirst() {
Node<T> c=head;
Node<T> b;
Node<T> q;
int size=0;
while(c!=null) { //Counting the size of the list
size++;
c=c.next;
}
for(int i=0;i<size;i++) {//Going through the list
c=head;
for(int j=0;j<size-i-1;j++) //Getting the elements in reverse order
c=c.next;
if(c.next!=null) {
b=c.next;
while(b!=null) {
if(c.getData().equals(b.getData())){ //Check repeated elements on the right side
q=head;
while(q.next!=c) {
if(q.getData().equals(c.getData()))//Check repeated elements on the left side
break;
q=q.next;
}
if(!q.getData().equals(c.getData())) {//Deletion occurs when there are elements on the right side only.
q.next=c.next;
break;}
}
b=b.next;
}
}
}
q=head;//We only needed to check the head once, so I separated the check from the loop.
b=head.next;
while(b!=null) {
if(q.getData().equals(b.getData())&&size!=0) {
head=head.next;
break;}
else
b=b.next; }
}
List<String> list = new LinkedList<String>();
Set<String> set = new LinkedHashSet<String>();
list.add("B"); list.add("A"); list.add("A"); list.add("R");
list.add("C");list.add("A");list.add("C");list.add("R");
for (String string : list) {
if (Collections.frequency(list, string) > 1) {
set.add(string);
}
}
for (String string : set) {
list.remove(string);
}
System.out.println(list);

The add method should insert elements into a list in sorted order

I have done this code for add the elements into LinkedList. Now I want to insert elements into a list in sorted order. How can I do this?
public void add(String element)
{
if (isEmpty())
{
first = new Node(element);
last = first;
}
else
{
// Add to end of existing list
last.next = new Node(element);
last = last.next;
}
}
My Main class is this for Linkedlist and arraylist which calls the method of SimpleLinkedList class and SimpleArrayListClass
package Comp10152_linkedlist;
import java.util.Random;
public class Comp10152_Lab4
{
public static void main(String[] args)
{
final int NUMBER_OF_ITERATIONS = 10;
String names[] = {"Amy", "Bob", "Al", "Beth", "Carol", "Zed", "Aaron"};
SimpleLinkedList ll = new SimpleLinkedList();
final int TOTALOPERATIONS = names.length * NUMBER_OF_ITERATIONS;
Random random = new Random();
for (int i=0; i<NUMBER_OF_ITERATIONS;i++)
{
for (int j=0; j<names.length; j++)
ll.add(names[j]);
}
System.out.println("The members of list are:");
System.out.println(ll);
// remove half of the items in the list by selecting randomly from names
for (int i=0; i<TOTALOPERATIONS/2;i++)
{
ll.remove(names[random.nextInt(names.length)]);
}
System.out.println("The members of list are:");
System.out.println(ll);
SimpleArrayList al = new SimpleArrayList();
try
{
for (int i=0; i<NUMBER_OF_ITERATIONS;i++)
{
for (int j=0;j<names.length;j++)
al.add(i,names[j]);
}
System.out.println("The members of array are:");
System.out.println(al);
// remove half of the items in the list by selecting randomly from names
for (int i=0; i<TOTALOPERATIONS/2;i++)
{
al.remove(names[random.nextInt(names.length)]);
}
System.out.println("The members of array are:");
System.out.println(al);
}
catch (Exception e)
{
System.out.println(e);
}
}
}
First insert the elements outside of the list, and then insert into the list by calling the add method.
How you sort elements outside the list depends on what data structures you use, what is the type of data, and what algorithms you want to apply.
While insertion into the list itself add in the sorted order.
First search the element in the sorted list which is greater than the element and then the element to be inserted and then add the new element before that.
Something like..
//Considering ascending order
public void add(String element) {
if(isEmpty) {
first = new Node(element);
last = first;
} else {
currentNode = first;
while(currentNode.next != null && currentNode.next.element > element) {
currentNode = currentNode.next;
}
Node newNode = new Node(element);
newNode.next = currentNode.next;
currentNode.next = newNode;
}
}

How would I make my custom generic type linked list in Java sorted?

I am writing my own linked list in java that is of generic type instead of using the java collections linked list. The add method for the linked list is made up of the following code:
public void add(T item, int position) {
Node<T> addThis = new Node<T>(item);
Node<T> prev = head;
int i;
if(position <= 0) {
System.out.println("Error: Cannot add element before position 1.");
}
else if(position == 1) {
addThis.setNext(head);
head = addThis;
} else {
for(i = 1; i < position-1; i++) {
prev = prev.getNext();
if(prev == null) {
System.out.println("Cannot add beyond end of list");
}
} // end for
addThis.setNext(prev.getNext());
prev.setNext(addThis);
}
} // end add
How would I make it so that when I add a new item, the item is compared to another item and is inserted alphabetically? I have looked into using compareTo but I cannot figure out how to do it.
Thanks
EDIT:
I have various classes: I have a class called Dvd which has methods and variables for a title(string) and number of copies of that title(int). I also have a linked list class, a listinterface, a node class, and a main class.
Does your implementation extend the java.util.List interface?
Can you simply add the object to the list, then sort the list using Collections.sort()?
You mention using generics but then mention sorting them alphabetically. Generics are not necessarily character strings, they are used to represent any type, while a sort property like alphabetically implies alphabetic characters. My Answer assumes you are expecting generic objects of type T which have an alphabetic nature to them. In my example I exclusively use a String
You can set you code up to search for the position to add itself instead of providing it.
public void add(T item) {
Node<T> addThis = new Node<T>(item);
Node<T> itr = head;
while (itr.hasNext()) {
if (addThis.compareTo(itr.getNext()) <= 0) { // itr > addThis
addThis.setNext(itr.getNext());
itr.setNext(addThis);
return;
}
itr = itr.getNext();
}
addThis.setNext(null);
itr.setNext(addThis);
return;
} // end add
Then in your Node class, you can implement the Interface Comparable . I'm assuming you store a string since you asked about alphabetizing. This Question Explains comparing strings alphabetically.
class Node implements Comparable<Node> {
String value; // ASSUMING YOU ARE USING A STRING AS YOUR GENERIC TYPE T
#Override
public int compareTo(Node otherNode) {
int i;
String thisString = this.getValue();
String otherString = otherNode.getValue();
int minSize = ( otherString.length() > thisString.length() ? thisString.length() : otherString.length() );
for (i = 0; i < minSize; i++) {
if (thisString.charAt(i) > otherString.charAt(i)) {
return 1;
} else if (thisString.charAt(i) < otherString.charAt(i)) {
return -1;
}
}
if (otherString.length() > thisString.length()) {
return 1;
} else if (otherString.length() < thisString.length()) {
return -1;
} else {
return 0;
}
}
// OTHER CLASS CONSTRUCTORS, VARIABLES, AND METHODS
}
In order to do this with simply generics, you would need to implement you Node class with the type T implementing Comparable like so:
class NodeNode<T extends Comparable<T>> implements Comparable {
T value;
#Override
public int compareTo(Node otherNode) {
return this.getValue().compareTo(otherNode.getValue());
}
// OTHER CLASS CONSTRUCTORS, VARIABLES, AND METHODS
}
I finally figured it out by using an insertion sort:
public void add(Dvd item) {
DvdNode addThis = new DvdNode(item);
if(head == null) {
head = addThis;
} else if(item.getTitle().compareToIgnoreCase(head.getItem().getTitle()) < 0) {
addThis.setNext(head);
head = addThis;
} else {
DvdNode temp;
DvdNode prev;
temp = head.getNext();
prev = head;
while(prev.getNext() != null && item.getTitle().compareToIgnoreCase
(prev.getNext().getItem().getTitle()) > 0) {
prev = temp;
temp = temp.getNext();
}
addThis.setNext(temp);
prev.setNext(addThis);
}
}

Categories