Using Arrays instead of Lists Java - java

This method has to remove duplicate elements from the passed-through array at 2 index points. However, I learned that we are not allowed to use Arraylist or LinkedLists, only Arrays. How can I make this work?
public Animal[] removeDuplicateAnimals(Animal[] animals, int fromIndex, int toIndex) {
int constFromIndex = fromIndex;
ArrayList<Animal> uniqueAnimals = new ArrayList<Animal>();
Animal[] uniqueAnimalsArray = new Animal[0];
uniqueAnimals.addAll(Arrays.asList(Arrays.copyOfRange(animals, 0, fromIndex)));
boolean existingFlag;
while (fromIndex < toIndex) {
existingFlag = false;
if(uniqueAnimals.size() == 0)
uniqueAnimals.add(animals[fromIndex]);
else {
int j = (constFromIndex - 1) > 0 ? (constFromIndex - 1): 0;
for (; j < uniqueAnimals.size(); j++)
if(uniqueAnimals.get(j).equals(animals[fromIndex])) {
existingFlag = true;
break;
}
if(!existingFlag)
uniqueAnimals.add(animals[fromIndex]);
}
fromIndex++;
}
uniqueAnimals.addAll(Arrays.asList(Arrays.copyOfRange(animals, toIndex, animals.length)));
return uniqueAnimals.toArray(uniqueAnimalsArray);
}

This has some unhandled edge cases (OOBExceptions etc), but if I understand what you're asking something like this should work:
public Animal[] removeDuplicateAnimals(Animal[] animals, int fromIndex, int toIndex) {
int modifiedAnimalsSize = animals.length;
for (int i = fromIndex; i < toIndex; i++) {
for (int j = i+1; j < toIndex; j++) {
int k = modifiedAnimalsSize -1;
if (animals[i].equals(animals[j])) {
animals[j] = animals[k];
animals[k] = null;
modifiedAnimalsSize--;
j--;
}
}
}
// return a new array which is resized
return Arrays.copyOf(animals, modifiedAnimalsSize);
}

For each animal at index i in the array, search through the indices of the array from i+1 to toIndex for the same animal; if there is a duplicate, write null at that index i in the original array. This will not resize the array. It will just replace duplicates with null.
public Animal[] removeDuplicateAnimals(Animal[] animals, int fromIndex, int toIndex) {
for (int i = fromIndex; i++; i < toIndex) {
for (int j = i+1; j++; j <= toIndex) {
if (animals[i].equals(animals[j])) {
animals[i] == null;
break;
}
}
}
return animals;
}

Related

Java ArrayList String Selection Sort

I'm struggling mightly on doing selection sort on an ArrayList of Strings to alphabetize them. I have no idea what I'm doing wrong. But its just not working properly for me. Heres my code.
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("d");
list.add("f");
list.add("c");
System.out.println(list);
int i;
int j;
int minValue;
int minIndex;
for (i=0; i<list.size(); i++) {
System.out.println(list.get(i));
char iLetter = (list.get(i).charAt(0));
int iValue = (int) iLetter;
minValue = iValue;
minIndex = i;
for(j=i; j<list.size(); j++) {
char jLetter = list.get(j).charAt(0);
int jValue = (int) jLetter;
if (jValue < minValue) {
minValue = jValue;
minIndex = j;
}
}
if(minValue < iValue) {
int temp = iValue;
char idx = list.get(minIndex).charAt(0);
int idxValue = (int) idx;
iValue = idxValue;
idxValue = temp;
}
}
System.out.println(list);
}
It still prints it out as ["a", "d", "f", "c"]
You are not updating your list anywhere in your loop, so it remains unsorted.
In order to actually swap elements of the list, replace:
if(minValue < iValue) {
int temp = iValue;
char idx = list.get(minIndex).charAt(0);
int idxValue = (int) idx;
iValue = idxValue;
idxValue = temp;
}
with:
if(minValue < iValue) {
Collections.swap (list, i, minIndex);
}
Collections.swap performs the following modification:
list.set(i, list.set(minIndex, list.get(i)));
Now the output will be
[a, c, d, f]
As mentioned, you need to do the actual swapping in the list, not just the temporary variables (doh!).
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("d");
list.add("f");
list.add("c");
System.out.println(list);
for (int i = 0; i < list.size(); i++) {
String smallest = list.get(i);
int smallestIndex = i;
for (int j = i; j < list.size(); j++) {
String value = list.get(j);
if (value.compareTo(smallest) < 0) {
smallest = value;
smallestIndex = j;
}
}
if (smallestIndex != i) {
String head = list.get(i);
list.set(i, smallest);
list.set(smallestIndex, head);
}
}
System.out.println(list);
}
Additionally, your code is just a single method, AKA spaghetti code. To make it more object-oriented you could make the following changes.
import java.util.*;
public class SelectionSort<T extends Comparable> {
private List<T> values;
public SelectionSort(List<T> values) {
this.values = values;
}
private void sort() {
for (int headIndex = 0; headIndex < values.size(); headIndex++) {
sortFrom(headIndex);
}
}
private void sortFrom(int headIndex) {
int smallestIndex = findSmallestFrom(headIndex);
if (smallestIndex != headIndex) {
swap(headIndex, smallestIndex);
}
}
private int findSmallestFrom(int i) {
int smallestIndex = i;
T smallest = values.get(i);
for (int j = i; j < values.size(); j++) {
T value = values.get(j);
if (value.compareTo(smallest) < 0) {
smallest = value;
smallestIndex = j;
}
}
return smallestIndex;
}
private void swap(int i, int j) {
T head = values.get(i);
values.set(i, values.get(j));
values.set(j, head);
}
public static void main(String[] args) {
List<String> values = createTestData();
System.out.println(values);
SelectionSort selectionSort = new SelectionSort<>(values);
selectionSort.sort();
System.out.println(values);
}
private static List<String> createTestData() {
List<String> values = new ArrayList<>();
values.add("a");
values.add("d");
values.add("f");
values.add("c");
return values;
}
}
Some of the changes I made:
Separate method for creation of test data
Separate method for printing the before and after state of the list and calling the sort
Create an instance instead of only static code
separate iterations and logic into meaningful methods
Rename the 'list' variable to 'values'. The fact that it's a list is already clear. The convention is to name a collection by the meaning of the data it contains
Introduced a generic type variable on the class (<T extends Comparable>). This allows any type of data to be sorted, as long as it implements the Comparable interface

How to write a remove method?

Write a method called get which will return an element from the given index. Returns -1 if the index is out-of-bounds.
Write a method called remove which will remove an element from the given index. Returns -1 if the index is out-of-bounds. Data should be shifted accordingly during removal.
//This is the get method
public int get(int index){
if(index < 0 || index >= size) {
return -1;
}else {
return data[index];
}
}
//This is the remove method
public int remove(int index){
if(index < 0 || index >= size){
return -1;
}else {
for(int i = 0; i < size-1; i++) {
index[i] = index[i+1];
}
}
}
This is as far as I got. Not sure how to proceed with the code. I'd appreciate if someone could guide me through. Thank you!
So far, you have the right idea. I am going to assume based on your syntax, that you are using an array. Your get() method looks good, but you are missing some code from your remove() method.
public int remove(int index){
//check for out-of-bounds
if(index < 0 || index >= size) //assumes size is set to the size of the array
{
return -1; }
else
{
for(int i = index; i < size-1; i++){
data[i] = data[i+1]; }
data[size-1] = 0; //assuming the array contains numbers, if not replace '0' with null
}
}
You need to replace the following :
for(int i = 0; i < size-1; i++) {
index[i] = index[i+1];
}
with:
for(int i = index; i < size-1; i++) {
data[i] = data[i+1];
}
Start the loop with index
index[i] won't compile. Should be data[i] probably.
Note:
This will not delete the last element. You need to specifically check for it.
public class MyList<T> {
T[] items = (T[])new Object[10];
public int size() {
int counter=0;
for (int i = 0; i < items.length; i ++) {
if (items[i] != null) {
counter ++;
}
}
return counter;
}
public void remove(int t) {
for (int i = t; i < items.length-1; i++) {
items[i]=items[i+1];
}
items[items.length-1]=null;
items= Arrays.copyOf(items,size());
}
}

How to access elements in a generic arraylist of arrays

I have been trying to access the elements of several arrays that are held within an array list. I am able to access it regularly, but the problem comes when I use generic type E to account for different data types. This gives me a class cast exception. If I change the type of tempStart and tempScan and corresponding casts to int[] (since that is what I am using to pass in) it runs.
public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list) {
if (list.get(0).getClass().isArray()) {
System.out.println(" I am an array!");
//go through the arrays and make sure they are
//not the same, remove any that are the same
//make flag to see if something is different
boolean matching;
for (int idx = 0; idx < list.size() - 1; idx++) {
E[] tempStart =(E[])list.get(idx);
for (int k = idx + 1; k < list.size(); k++) {
matching = true;
E[] tempScan = (E[])list.get(k);
for (int index = 0; index < tempStart.length; index++) {
if (tempStart[index] != tempScan[index]) {
matching = false;
}
}
if (matching) {
list.remove(tempScan);
k--;
}
}
}
You are trying to cast E to E[] and it's obviously not correct. Try something like:
import java.lang.reflect.Array
...
public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list) {
ArrayList<E> retList = new ArrayList<>(list.size());
if (list.isEmpty()) return retList;
if (list.get(0).getClass().isArray()) {
boolean matching;
for (int idx = 0; idx < list.size() - 1; ++idx) {
E tempStart = list.get(idx);
for (int k = idx + 1; k < list.size(); k++) {
matching = true;
E tempScan = list.get(k);
int tempStartLen = Array.getLength(tempStart);
for (int index = 0; index < tempStartLen; index++) {
if (Array.get(tempScan, index) != Array.get(tempStart, index)) {
matching = false;
}
}
if (matching) {
list.remove(tempScan);
k--;
}
}
}
return retList;
} else {
throw new IllegalArgumentException("List element type expected to be an array");
}
}
However because we are using Java Reflection Array to manipulate the array operation, using generic E doesn't make sense here. You can simple declare it as ArrayList<Object>
Updates: as #afsantos comments below, the parameter type ArrayList could be declared as ArrayList<?> as nothing is going to be insert into it.

Insertion sort, number of comparisons

Hi all for an assignment we must count the number of comparisons for a number of algorithms. I'm using the code in the book "Algorithms" by Sedgewick & Wayne. I don't see where my code is wrong actually... As soon we going to compare something I count my comparison...
public long sort(Comparable[] a) {
if (a == null) {
throw new IllegalArgumentException("argument 'array' must not be null.");
}
int N = a.length;
for (int i = 0; i < N; i++) {
for (int j = i; j > 0; j--) {
this.comparisons++;
if(less(a[j], a[j-1]))
exch(a, j, j-1);
}
assert isSorted(a, 0, i);
}
assert isSorted(a);
return this.comparisons;
}
the less method which I use:
private boolean less(Comparable v, Comparable w) {
return (v.compareTo(w) < 0);
}
It must pass this test
Integer[] array = {4, 2, 1, 3, -1};
Comparable[] arrayClone1 = array.clone();
Comparable[] arrayClone2 = array.clone();
long nbCompares1 = i.sort(arrayClone1);
long nbCompares2 = i.sort(arrayClone2);
System.out.println("1" + nbCompares1);
System.out.println("2" + nbCompares2);
those two should be equal....
The isSorted methods:
private boolean isSorted(Comparable[] a) {
System.out.println("here");
return isSorted(a, 0, a.length - 1);
}
// is the array sorted from a[lo] to a[hi]
private boolean isSorted(Comparable[] a, int lo, int hi) {
System.out.println("here1");
for (int i = lo + 1; i <= hi; i++)
if (less(a[i], a[i-1])) return false;
return true;
}
Someone ideas about this? Help will be appreciated!
Number of comparisons should be exactly N*(N-1)/2. Maybe you mess with comparisons field in somewhere else, so I would advise to use local variable instead:
public long sort(Comparable[] a) {
if (a == null) {
throw new IllegalArgumentException("argument 'array' must not be null.");
}
int N = a.length;
int comparisonsCount = 0; // use this instead
for (int i = 0; i < N; i++) {
for (int j = i; j > 0; j--) {
comparisonsCount++; // edit here
if(less(a[j], a[j-1]))
exch(a, j, j-1);
}
assert isSorted(a, 0, i);
}
assert isSorted(a);
return comparisonsCount; // and here
}

Trying to access an array from ArrayList

I'm trying to Sort an array from my ArrayList:
ArrayList<Integer> al = new ArrayList<Integer>();
al.insert(0, 4);
al.insert(1, 3);
al.insert(2, 2);
al.insert(3, 1);
SelectionSortWrappers<Integer> ss = new SelectionSortWrappers<Integer>();
ss.sort(al.elements);
ss.show(al.elements);
But when I try to access al.elements, I'm getting:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
Here is my SelectionSort Class:
public class SelectionSortWrappers<T>{
public <T extends Comparable<? super T>> void sort(T[] array){
int index;
for(int i = 0 ; i < array.length;i++){
index = i;
for(int j = i + 1; j < array.length; j++){
if (array[j].compareTo(array[index]) < 0){
index = j;
}
}
T smaller = array[index];
array[index] = array[i];
array[i] = smaller;
}
}
public void show(T[] array){
for(int i=0; i < array.length; i++){
System.out.print(array[i] + " ");
}
}
}
My ArrayList, i had to create, because is for my university project, i cannot use the Java one.
package Lists;
public class ArrayList<T> implements List<T> {
private static int MAX_SIZE = 10;
private static final int NOT_FOUND = -1;
public T[] elements;
protected int size;
public ArrayList() {
size = 0;
elements = (T[]) new Object[MAX_SIZE];
}
public T[] getArray(){
return elements;
}
public int find(T v) {
for(int i = 0; i < size; i++) {
if(v == elements[i]) {
return i;
}
}
return NOT_FOUND;
}
public T elementAt(int pos) {
if(pos >= 0 && pos < size) {
return elements[pos];
}
throw new InvalidArgumentException();
}
public void insert(int pos, T v) {
if (size == MAX_SIZE){
elements = Arrays.copyOf(elements, size * 2);
MAX_SIZE = size * 2;
}
if(pos == size) {
elements[size] = v;
}
else {
for(int i = size; i > pos; i--) {
elements[i] = elements[i-1];
}
elements[pos] = v;
}
size++;
}
public void remove(int pos) {
if(pos >= 0 && pos < size) {
for(int i = pos; i < size-1; i++) {
elements[i] = elements[i+1];
}
size--;
}
else {
throw new InvalidArgumentException();
}
}
public int size() {
return size;
}
public void show(boolean reverse) {
if (!reverse){
for(int i=0; i < size; i++){
System.out.print(elements[i] + " ");
}
} else {
for(int i=size; i >= 0; i--){
System.out.print(elements[i] + " ");
}
}
}
}
Where is the problem? My elements field is public.
You're running into the predictable erasure-versus-arrays problem caused by doing (T[]) new Object[MAX_SIZE]. You'll get a warning on that line -- that warning is warning you about exactly this problem.
Your ArrayList class is pretending an Object[] is a T[], but it really isn't -- the actual referenced array is still an Object[]. When you pull it out with al.elements, it tries to actually cast it to an Integer[] and fails.
You will have to do something ugly to deal with this -- like what the built-in java.util.Collection.toArray(T[]) has to do, for example. Alternately, you could write your sorting method to access your ArrayList directly instead of trying to work on its underlying array.

Categories

Resources