How to check if an array is filled enough in java? - java

I want to check if an array is at 75% filled with objects and if it's true i have to resize it. In the variable size i have my objects (!=null) and i have an array of integers ints
public class PQ {
private int[] pq;
private int size;
public PQ(int capacity) {
if (capacity < 1) {
throw new IllegalArgumentException();
}
this.pq = new int[capacity + 1];
this.size = 0;
}
public void insert(int number) {
//Code
}
private int[] resize() {
int[] newPQ = new int[this.pq.length * 2];
for (int i = 0; i < this.pq.length; i++) {
newPQ[i] = this.pq[i];
}
return newPQ;
}
}

Try this:
Whenever you add an element, we increment size (this will track the number of non-empty spaces so that you don't need to continually recount your array). Then we compare this number to the total length of your array. If count is at least 75% of the size of the array, we call your resize method and set pq to the new array it returns. I assume that you wish to add to the end of the array, and that you don't want empty indexs between numbers. If you want gaps you will need to use a loop which I am trying to avoid for efficiency's sake, if it isn't necessary. Assuming you don't, you can just add to your array at index size since this will be the first non-empty element.
//O(1) efficiency if you don't need to resize, O(n) if you do
public void insert(int number) {
if(size / pq.length >= 75) {
pq = resize();
}
pq[size] = number; //Since this will be the first non-empty index
size++;
return; //Doing it this way, if you can, is much more efficient than looping
}
If you call remove and take out from anything but the end you are going to have to shift everything down so that you don't have empty space.
If you are going to have empty indexes, try something like this (to insert at the first empty index encountered by the loop)...Let's use an Integer[] instead so that you can check for null and don't have to worry about any 0's in the array being counted as empty (int[] initiates everything to 0).
That way we can check for empty space and 0's are not counted as empty space in case you use any in your int[].
//O(n) efficiency if you don't need to resize, O(n^2) if you do
public void insert(int number) {
if(size / pq.length >= 75) {
pq = resize();
//You would have to make resize return an Integer[] and
//implement this throughout the code
}
for(int i = 0; i < pq.length; i++) {
if(pq[i] == null) {
pq[size] = number;
size++;
return;
}
}
}
Regardless:
Remember when you call remove() to decrement size.

What you could do is have an integer instance variable called count, that keeps track of the number of elements in the pq array. And whenever you insert an element into the array through the insert method, you can increment the count variable. Whenever you remove an element from the array through a remove method, you can decrement the count variable. Then, you can use this to check if the array is 75% filled at least,
if(pq.length * .75 <= size){
//do what you need to do here
}
And the class would look like this,
public class PQ {
private int[] pq;
private int size;
public PQ(int capacity) {
if (capacity < 1) {
throw new IllegalArgumentException();
}
this.pq = new int[capacity + 1];
this.size = 0;
}
public void insert(int number) {
size++;
//Code
}
public void remove(int number) {
size--;
//Code
}
private int[] resize() {
int[] newPQ = new int[this.pq.length * 2];
for (int i = 0; i < this.pq.length; i++) {
newPQ[i] = this.pq[i];
}
return newPQ;
}
}

You are explicitly storing the size as a variable. You also know the backing array's size. Compare them at the point when you need to check size: if(this.size > 3*this.pq/4).

Use ArrayList do everything automatically for you in more efficient way.
Edited:
it is the initialization, all put -1
this.pq = new int[capacity + 1];
Arrays.fill(pq, -1);
then when you check you do like this:
if(pq[pq.length*.75] != -1) {
// then is means that is has already filled up 75%
} else {
// not filled 75% yet
}

Related

Need help developing a proper print method for this Java program

This program takes integers from user input and puts them in a collection. It then prints the positive values first, then the negative values, and doesn't print repeated numbers. It stops asking for input once the user enters 0. Here is the code:
public class Intcoll2
{
private int[] c;
private int[] d;
private int howmany = 0;
public Intcoll2()
{
c = new int[500];
}
public Intcoll2(int i)
{
c = new int[i]
}
public void insert(int i)
{
if (i > 0)
{
int j = 0;
while ((j <= howmany) && (c[j] != i)) j++;
if (j == howmany)
{
if (j == c.length - 1)
{
d = new int[2*c.length];
for (int k = 0; k<c.length; i++){
d[k] = c[k];
}
c = d;
}
c[j] = i; c[j + 1] = 0;
}
howmany++;
}
}
public int get_howmany()
{
int j=0, howmany=0;
while (c[j]!=0) {howmany++; j++;}
return howmany;
}
Now my current print method looks like this:
public void print()
{
int j = 0;
System.out.println();
while (j <= howmany)
{
System.out.println(c[j]); j++;
}
}
But when I try to use that in my client, it only prints out zeros. Any help with what I'm doing wrong would be greatly appreciated.
An answer that you were probably not looking for, but still on the only real answer you should care about.
Your problem is not that somewhere in that code a bug is hiding. The problem is that your code is confusing beyond limits:
Dont use single-character variable names.
The constructor that takes an int ... creates an empty array!
Dont say "collection" when you are using arrays.
Dont give fields and local variables the same name.
Seriously: understanding this mess is mainly complicated and hard because you wrote code that is hard to read.
Now you are asking other people to debug such complicated code that you (the author who created it!) do not understand in the first place.
Instead, you might throw this whole thing away. And slowly write it again; but in a way that isn't at all confusing to the reader.
I took a look at your class and rewrote it in a more legible manner. I didn't test it but I'm confident it works. You can check it out and hopefully understand what's happening. Hope this helps!
public class IntCollection2 {
private int[] collection; // A large allocation, not neccessarily filled up.
private int currentSize; // The number of spots currently filled in the collection.
public IntCollection2() {
collection = new int[500];
currentSize = 0;
}
public IntCollection2(int size) {
collection = new int[size];
currentSize = 0;
}
/**
* Inserts a new element into the internal array. If the current array is filled up,
* a new array double the size of the current one is allocated.
* #param element An int to insert into the collection. Must not be '0'.
* #return True if the element was successfully inserted, false if the element was
* equal to '0' and was ignored.
*/
public boolean insert(int element) {
if (element != 0) {
if (currentSize < collection.length - 1) {
collection[currentSize] = element;
} else {
int[] newCollection = new int[collection.length * 2];
for (int i = 0; i < currentSize; i++) {
newCollection[i] = collection[i];
}
newCollection[currentSize] = element;
collection = newCollection;
}
currentSize++;
return true;
} else {
return false;
}
}
/**
* Not actually necessary because the class automatically updates its currentSize
* every time a new element is inserted.
* #return The current number of filled spots in the internal array.
*/
public int getCurrentSize() {
int size = 0;
for (int i = 0; i < collection.length && collection[i] != 0; i++) {
size++;
}
return size;
}
/**
* Prints out all the elements currently in the collection, one on each line.
*/
public void print() {
System.out.println();
for (int i = 0; i < currentSize; i++) {
System.out.println(collection[i]);
}
}
}
FYI: this class just prints out every element in the collection, in order. You mentioned something about printing positive then negative values, but I leave that to you.
EDIT: I'm guessing you're brand new to programming, so I just want to clarify exactly what a collection is. An array is an ordered list of elements. When you create an array, the computer sets aside a bit of memory to hold exactly the number of elements you told it to. You cannot change the size of an existing array. A collection is basically a wrapper around an array. It makes a bigger array than it needs to hold its elements, and when its array becomes full, it allocates a new, bigger one that can hold more elements.

Sorting Integer array using Comparable

I am working on a project in which I have to sort an array of Integer objects by using Comparable.
My add method takes an item of type E. If my size variable (which tracks the elements in my array theData[]) is = 0 (which it is initialized to), I simply put the item in theData[0].
If it is not, I use item.compareTo to compare the item against each item already in the array. If the result of compareTo is < 0 for a number in the array, I shift everything at that number and after to the right, and insert the item before it.
If compareTo returns a 0, meaning the item is equal to the number in the array, I do nothing as I don't want duplicates in the array.
If none of the compareTo statements in the loop return a -1 or a 0, I put the item in theData[size], the end of the array, as it must be larger than all the other numbers.
However, this doesn't work. Any time I make a new Set and add a few numbers to it, then try to print out the contents of my set using a for loop,I keep getting a java.lang.ArrayIndexOutOfBoundsException: 10 error for this line:
theData[j + 1] = theData[j];
I've tried starting from scratch and re-writing my loop with different logic, and each time I keep hitting this wall. I know I must either be shifting incorrectly or not increasing the size of the array correctly with my reallocate method, but I can't wrap my head around it.
import java.util.*;
public class Set<E extends Comparable<E>> {
String s;
String name;
private static final int INITIAL_CAPACITY = 10;
private E[] theData;
private int size = 0;
private int capacity = INITIAL_CAPACITY;
#SuppressWarnings("unchecked")
public Set() {
theData = (E[]) new Comparable[capacity];
}
public Set(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void add(E item) {
if (size == capacity) {
reallocate();
}
if (size == 0) { // If size is 0, add item to theData[0]
theData[size] = item;
size++;
return;
}
else { // Else compare the item to every item in loop.
for (int i = 0; i < size; i++) {
int result = item.compareTo(theData[i]);
if (result < 0) {
for (int j = 0; j < size; j++) { //If item is less than a number, shift everything
theData[j + 1] = theData[j]; //after that index to the right, and add item
theData[j] = item;
}
}
if (result == 0) {
return;
}
else { //If item is not less than or equal to any
theData[size] = item; //numbers in the array, add it to the end
size++;
}
}
}
}
/*
* if (size>=1){ int result = item.compareTo(theData[size-1]); if(result<0){
* E temp = theData[size-1]; theData[size-1] = item; theData[size] = temp; }
* if(result>1){ return; } }
*/
public E get(int index) {
if (index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException(index);
}
return theData[index];
}
public int size() {
return size;
}
private void reallocate() {
capacity = 2 * capacity;
theData = Arrays.copyOf(theData, capacity);
}
}
Edit: The driver method I'm using to test it -
public class Driver {
String one = "two";
public static void main(String[] args){
Set<Integer> one = new Set<Integer>();
one.add(63);
one.add(20);
one.add(127);
one.add(10);
one.add(26);
one.add(15);
for(int i = 0; i < one.size(); i++){
System.out.println(one.get(i));
}
}
}
When j == size - 1, theData[j+1] will take you out of the array.
You want to loop to one before the end instead.
for (int j = 0; j < size - 1; j++) { //If item is less than a number, shift everything
theData[j + 1] = theData[j]; //after that index to the right, and add item
theData[j] = item;
}
So I've also taken a look at the logic you've got for the insertion, and it doesn't make a lick of sense. Why do you delay the insertion at all? If you've got the room, just add it!
Next, the double loops are essentially implementing bubble sort, but there's a fatal flaw with it: you don't ever complete the swap; you only overwrite your values repeatedly. You're also not comparing in the right direction; you want to swap if the value on the left is larger than the value on the right, since you're starting from the beginning of the array.
So, with that...this is what an implementation would have the form of...
public void add(E item) {
if (size == capacity) {
reallocate();
}
theData[size++] = item;
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - 1; j++) {
if (theData[j].compareTo(theData[j + 1]) > 0) {
// perform the swap (you need an extra variable!
}
}
}
}
I leave implementing the swap as an exercise for the reader.
First, in your shift loop, you are inserting the new item in every position instead of shifting then inserting in [i] because you copy theData[j] to the next position, but always assign item to theData[j], is that right?
Second, you are starting from the beginning of array since j starts with 0. J should start with i.
Third and main bug, you verify if result < 0 then you verify IF result == 0, change for a ELSE IF so the else don't get executed even when result < 0
shift elements to right can be done from right to left, like:
for (int j = size; j > i; j--) { // If item is less than a
// number, shift
// everything
theData[j] = theData[j - 1]; // after that index to the
// right, and add item
}
size++;
theData[i] = item;
break;// after insert the number, we can just break the for loop
once the new number is inserted, break the for loop, else, the size variable will not be correct
else { // If item is not less than or equal to any
theData[size] = item; // numbers in the array, add it to the end
size++;
break;
}

how to delete a value from an array and shrink the array?

I've been doing tons of programming challenges and have lately encountered this problem: how to delete a value from an array and then shrink the array? I know how to tackle the problem by using the Arraylist and its methods but I'd like to know how to do the problem from scratch by using the basic array with fixed size. I'd really appreaciate if smb explains the solution elaborately.
public static int[] shrinkArray(int key)
{
int[] resultArray = new int[myArray.length];
for(int i = 0; i < myArray.length; i++)
{
if(myArray[i] == key)
break;
}
return resultArray;
}
You almost have it.
public static int[] shrinkArray(int key)
{
int[] resultArray = new int[myArray.length-1]; //One length less as we removed an item
boolean found = false;
for(int i = 0, j = 0; i < myArray.length; i++, j++)
{
if(!found && myArray[i] == key){ //if we find item first time
i++; //skip it
found = true; //we found first occurrence
}
if(j < resultArray.length)
resultArray[j] = myArray[i]; //copy array
}
if(found)
return resultArray;
return myArray; //not found
}
Perhaps converting your array to an arraylist then using the remove() method of the arraylist class would work. Then you could take said arraylist and convert it back to an array. Both conversions could work with a for-loop.
Another option would be to take an array. Find the index of the value you want to remove. Then make a for loop starting at that index that shifts all of the values to the right of that index then puts those values one index to the left.
Here is re sizable array that will change capacity on remove and add operations (when capacity is reached). Did not test this much but looks okay.
public class ArrayBackedIndexedCollection {
private int size;
private int capacity;
private Object[] elements;
public ArrayBackedIndexedCollection(){
this.capacity = 1;
this.elements = new Object[capacity];
}
public ArrayBackedIndexedCollection(int initalCapacity){
/***************************************************
if initial capacity is less then 1 -> throw
exception
**************************************************/
this.capacity = initalCapacity;
this.elements = new Object[initalCapacity];
}
public int size(){
return size;
}
public void add(Object object){
// if capacity is reached
if ( size == capacity){
Object[] tmp = new Object[capacity];
// backup current array
System.arraycopy(elements, 0, tmp, 0, elements.length);
// re size to double capacity
elements = new Object [2*capacity];
// copy backup into re sized elements array
System.arraycopy(tmp, 0, elements, 0, tmp.length);
capacity = 2 * capacity;
}
this.elements[size] = object;
size++;
}
public Object get(int index){
return this.elements[index];
}
public void remove(int index){
elements[index] = null;
size --;
System.arraycopy(elements, index, elements, index + 1, size() - index);
}
public void insert(Object value, int position){
//...
}
}
Once you have created an array object in java you cannot resize it. If you want an array of different size you will have to create a new array and then populate it from scratch.
As you can imagine this is very inefficient and performance heavy. You are better off using an ArrayList or LinkedList. As a general rule you should favour collections over arrays, but if you're just looking to solve the challenge here's how I'd do it:
public static int[] shrinkArray(int keyToRemove, int[] arrayToRemoveFrom){
int[] resultArray = new int[arrayToRemoveFrom.length - 1];//new array is one smaller
boolean itemRemoved = false;
for(int i = 0, j = 0; i < resultArray.length; i++, j++){
if(!itemRemoved && arrayToRemoveFrom[i] == keyToRemove){
itemRemoved = true;//boolean so you only get in here once
i--;//decrease i for result array so you done leave a blank space
}else{
resultArray[i] = arrayToRemoveFrom[j];
}
}
return resultArray;
}

Storing a 2d array elements in an arrayList

I have a 2d grid of integers.
grid[][];
Suppose I am given an element randomly from the 2d array. My aim is to return its adjacent grid elements.
For that I am creating an ArrayList
ArrayList<int[][]> adjacentSidesList = new ArrayList<int[][]>();
I would have to go for quite a few number of cases and in each case the number of the adjacentSides would be different. So my choice of data structure is an ArrayList
But when I would add an element to the list
adjacentSidesList.add(grid[row][column+1]);
I understand this is wrong because I am adding the value of the grid element to the ArrayList and not the element itself. Does anyone have any idea on how to store the arrayElements in the arrayList and not the value stored in them ??
Any alternate method is also welcome with the reasons why the method is better
Thanks in Advance
Your grid object is a two-dimensional integer array. grid[row][column+1] is an integer, located in the respective indexes in your grid.
adjacentSidesList.add(grid[row][column+1]);
will not work, because you want to add an int to a list of ArrayList of two-dimensional int arrays. I believe you want to store numbers and you want to know what are those numbers. I wonder about the definition of neighbor. I will suppose here that the neighbor is the element located up, down, left or right to the current element, or, to put it more scientifically, the elements being located exactly at a distance of 1 from the current element in Taxicab-geometry.
The first problem is that a point might be at the margin of your space, which would mean they do not have a neighbor. The next problem is a general formula for the neighbors. I believe your numbers should be aware of their position, therefore we should define the following class:
public class GridHandler {
private static GridHandler[][] grid;
private int i;
private int j;
private int value;
public static void init(int[][] input) {
int rowNumber = input.length;
int columnNumber = input[0].length;
grid = new GridHandler[rowNumber][columnNumber];
for (int r = 0; r < rowNumber; r++) {
for (c = 0; c < columnNumber; c++) {
grid[r][c] = new GridHandler(r, c, input[r][c]);
}
}
}
public static GridHandler[][] getGrid() {
return grid;
}
public GridHandler(int i, int j, int value) {
this.i = i;
this.j = j;
this.value = value;
grid[i][j] = this;
}
public int getValue() {
return value;
}
public void setValue(value) {
this.value = value;
}
public int getLeftValue() throws ArrayIndexOutOfBoundsException {
if (j == 0) {
throw new ArrayIndexOutOfBoundsException("Left edge");
}
return grid[i][j - 1].getValue();
}
public int getUpValue() throws ArrayIndexOutOfBoundsException {
if (i == 0) {
throw new ArrayIndexOutOfBoundsException("Up edge");
}
return grid[i - 1][j].getValue();
}
public int getRightValue() throws ArrayIndexOutOfBoundsException {
if (j == grid[0].length - 1) {
throw new ArrayIndexOutOfBoundsException("Right edge");
}
return grid[i][j + 1].getValue();
}
public int getDownValue() throws ArrayIndexOutOfBoundsException {
if (i == grid.length - 1) {
throw new ArrayIndexOutOfBoundsException("Down edge");
}
return grid[i + 1][j].getValue();
}
}
Now, if you use that class, each element will be aware of their neighbors. You can initialize the whole thing like this:
GridHandler.init(grid);
I hope this helps.
You could create a new class which will hold row and column index of 2D array element like:
class Index {
private int row;
private int column;
//getter and setters
}
Now when you want to store the data in list, you store the index object and when you have to access the element, you can access it like:
Index index = adjacentSidesList.get(0);
int element = grid[index.getRow()][index.getColumn()];

Finding elements in array with binary search

Trying to use Arrays.binarySearch() to search for a string in an array and return the index. However each time I call Arrays.binarySearch() I get the following exception -
Exception in thread "main" java.lang.NullPointerException
at java.util.Arrays.binarySearch0(Unknown Source)
at java.util.Arrays.binarySearch(Unknown Source)
at project.ArrayDirectory.lookupNumber(ArrayDirectory.java:97)
at project.test.main(test.java:12)
Here is my ArrayDirectory class -
public class ArrayDirectory implements Directory {
static Entry[] directory = new Entry[50];
#Override
public void addEntry(String surname, String initials, int extension) {
int n = 0;
for (int i = 0; i < directory.length; i++) { // counting number of
// entries in array
if (directory[i] != null) {
n++;
}
}
if (n == directory.length) {
Entry[] temp = new Entry[directory.length * 2]; // if array is full
// double the
// length.
for (int i = 0; i < directory.length; i++)
temp[i] = directory[i];
directory = temp;
}
int position = -1;
for (int i = 0; i < directory.length; i++) {
position = i;
if (directory[i] != null) { // sorting the array into alphabetical
// order by surname.
int y = directory[i].getSurname().compareTo(surname);
if (y > 0) {
break;
}
}
else if (directory[i] == null) {
break;
}
}
System.arraycopy(directory, position, directory, position + 1,
directory.length - position - 1);
directory[position] = new Entry(initials, surname, extension); // placing
// new
// entry
// in
// correct
// position.
}
#Override
public int lookupNumber(String surname, String initials) {
// TODO Auto-generated method stub
Entry lookup = new Entry(surname, initials);
int index = Arrays.binarySearch(directory, lookup);
return index;
}
}
Any ideas how I use binary search to find the correct index?
Thank you for you help.
edit -
I have also overridden comapreToin my Entry class -
public int compareTo(Entry other) {
return this.surname.compareTo(other.getSurname());
}
In your invocation of
int index = Arrays.binarySearch(directory,lookup);
directory seems to contain only null elements. Check that you are initializing elements correctly.
I note two things:
static Entry [] directory = new Entry [1];
First, that code allocates space for one Entry in the array. It doesn't actually instantiate an Entry. That is, directory[0] is null. Secondly, a binary-search on an array with one entry is crazy. There is only one element. It must be directory[0]. Finally, you should sort your array to do a binary search on it.
The basic concept behind a binary search is the recursion of the following steps(Note the search assumes the list or array of elements is sorted in some form and the element exists there.):
Go to the middle element of the array.
check if the searched element is equal to the element at the middle. If it is then return its index.
if not then check if the searched element is 'smaller' or 'larger' than the element in the middle.
if it is smaller then go to step 1 using only the lower/first half of the array instead of the whole.
else go to step 1 using only the upper/last half of the array instead of the whole.
As the array is continuously divided in 2 it will eventually reach the size of 1 giving the result.
Now, suppose you are looking for an integer in an int array. Here is what the code would be like:
public static int binarySearch(int number, int[] array)
{
boolean isHere = false;
Integer index =0;
for(int i=0;i<array.length;i++)
{
if(array[i] == number)
{
isHere = true;
i = array.length;
}
}
if(!isHere)
{
index = -1;
}
else
{
int arrayStart = 0;
int arrayEnd = array.length;
index = binarySearch(number, arrayStart, arrayEnd, array);
}
return index;
}
private static int binarySearch(int number, int start, int end, int[] array)
{
// this formula ensures the index number will be preserved even if
// the array is divided later.
int middle = (start+ end)/ 2;
if(array[middle] == number)
{
return middle;
}
else
{
if(number < array[middle])
{
//searches the first half of the array
return binarySearch(number, start, middle, array);
}
else
{
// searches the last half of the array
return binarySearch(number, middle, end, array);
}
}
}
You can use the compareTo() method instead of <,>, & == operators in your example. The logic should still be the same.

Categories