This question already has answers here:
How do I remove objects from an array in Java?
(20 answers)
Closed 1 year ago.
I am currently working on a delete method on a fixed array. Here is the implementation of the delete method below. What it does in the first for-loop is it gets the index if the data has a match on the array. For the next if and for-loop, its supposed to move the contents of the index if for example, the element deleted is at the 2nd or 3rd index of an array of length 5. It returns true, if the element has been successfully deleted in the array and false if not.
public boolean delete(E data) {
int index = -1;
int size = list.length;
for (int i = 0; i < list.length; i++) { // for getting what index in the array
if (data == list[i]) { // is the element in if there is a match
index = i;
}
}
if (index > -1) { // for swapping the index when
final int newArraySize; // the element is deleted in the
if ((newArraySize = size - 1) > index) { // between first-2nd to the last
for (int x = 0; x < list.length; x++) { // index in the array.
if (list[x] == null) {
for (int y = 0; y < x; y++) {
// move items
list[y] = list[y+1];
}
}
}
}
list[size = newArraySize] = null;
return true;
}
return false;
}
When I try running it, it doesn't delete the element. I'm having problems with the implementation of the swapping index part. I need help.
Your solution has time complexity of O(nxn). Instead you can start from the index of element being removed and swap all elements from index of element being removed.
for (int i = index; i < list.length - 1; i++) {
list[i] = list[i + 1];
}
But above solution might retain same size of the array and have repeat elements.
I will suggest using two array solutions, it adds bit of space complexity but effectively removes element and reduces the array size. Also you need to return this updated array.
int[] copy = new int[list.length - 1];
for (int i = 0, j = 0; i < list.length; i++) {
if (i != index) {
copy[j++] = list[i];
}
}
Related
I created a method to remove entire rows from 2D arrays in Java. I created this method because I wanted to remove a row if a certain condition applied. Although, when I use the remove method inside a for loop (for the matrix I am trying to remove) it creates an index out of bounds error. I believe this is because the length of the array is changing. That's why I saved the arr.length inside a variable and I am reducing it inside the for loop. However, I still have an index out of bounds error in java. This is my code:
//for loop
for (int index = 0; index < size; index++) {
if (TheMatrix[index][0] == TheMatrix[0][0]) {
TheMatrix = removeRow(TheMatrix, index);
size--;
}
}
//method for deleting row
public static int[][] removeRow(int[][] TheMatrix, int index) {
int[][] arrAux = new int[TheMatrix.length-1][7];
for (int i = 0; i < arrAux.length; i++) {
for (int j = 0; j < 7; j++) {
arrAux[i][j] = TheMatrix[i][j];
int z = i+1;
if (i == index) {
arrAux[i][j] = TheMatrix[z][j];
}
if (i > index) {
arrAux[i][j] = TheMatrix[z][j];
}
}
}
TheMatrix = Arrays.copyOfRange(arrAux, 0, arrAux.length);
return TheMatrix;
}
The method for deleting the row works perfectly, the for loop is the one generating the problem.
Any solution would be appreciated, thank you!
The job of this method is to remove the value toRemove from the array. The remaining elements should just be shifted toward the beginning of the array. (The array's size will not change.) Since the array will now have one fewer element, the position of the last element should just be filled with 0. If there is more than one occurrence of toRemove in the array, only the first occurrence should be removed. The method has no return value, and if the array has no elements, it should just have no effect.
The solution:
public static void remove(int[] arr, int toRemove) {
boolean done = false;
int position = 0;
for(int pos = 0; pos < arr.length; pos++) {
if(!done && arr[pos] == toRemove) {
done = true;
position = pos;
}
if(done) {
for(int i = position + 1; i < arr.length; i++) {
arr[i - 1] = arr[i];
}
arr[arr.length -1] = 0;
}
}
}
I am not following how this algorithm works. The use of boolean confuses me, I feel I don't fully understand what the primitive data type does, I know that it holds two things either true or false, and false by default. But what does that really mean? I don't understand boolean.
I understand why would want an int placeholder for the index of where the toRemove value was found. I understand we would want to use a for-loop to iterate one-by-one the indices and their respective values and pinpoint where exactly toRemove is found. I understand we would want a check point conditional to see if at some arbitrary index the toRemove value exists, andd therefore:
if(arr[pos] = toRemove) // then bingo we've found him
I don't understand the boolean !done, booleans confuse me.
why after this check point is there done = true? and then after that another check if(done)? and why another for loop for(int i = position + 1; i < arr.length; i++) and after that for loop the line arr[i - 1] = arr[i];? and finally at the end arr[arr.length-1] = 0 and position = pos;
I understand when we want to access a particular indicies value we write variablenameOfArr then the [] and put it inside the box. I am having difficulty putting this all together.
Thank you
In this case, the boolean done seems to control whether a value has already been removed or not. It begins the algorithm as false, as nothing has been removed yet.
The first if statement tests to see if the value of done is false. In if statements, instead of saying if(done == false), this can be simplified to if(!done). So, this if statement simply tests to see if a value has been found yet or not.
done is then set to true once a value has been removed, so that no future values will be removed.
Finally, the second if statement tests to see if a value has been removed or not. Like the first if statement, if(done == true) can be simplified to if(done).
I hope this helps, comment with any further questions if they arise.
public static void remove(int[] arr, int toRemove) {
boolean done = false; //This boolean is used to determine when the element has been found
int position = 0;
for(int pos = 0; pos < arr.length; pos++) { //Iterating through the array
//if we aren't already done, (!done = NOT DONE) and we have found the position to remove, then enter this logic
if(!done && arr[pos] == toRemove) {
done = true; //since we found the position to remove, set done to true
position = pos; //Save the index of the one that was removed
}
if(done) { //if we are done, enter this logic
//This loop starts above the index where removed, and iterates to the top
for(int i = position + 1; i < arr.length; i++) {
arr[i - 1] = arr[i]; //This shifts each element down one
}
arr[arr.length -1] = 0; //This sets the empty slot at the top of the array to 0
}
}
}
The boolean is indeed not necessary since it is always true when if(!done && arr[pos] == toRemove) is true.
Besides, it makes no sense to go on the outer loop when you have removed an element as 1) the state of the array is nice : the inner loop has shifted the elements after the removed element to their left and 2) you cannot perform two removals.
By the way the position variable is also not required. You can use the pos variable directly as it is read only used.
This code :
for(int pos = 0; pos < arr.length; pos++) {
if(!done && arr[pos] == toRemove) {
done = true;
position = pos;
}
if(done) {
for(int i = position + 1; i < arr.length; i++) {
arr[i - 1] = arr[i];
}
arr[arr.length -1] = 0;
}
}
could be replaced by this without using the boolean and you could also exist the method after the array elements were shifted :
for(int pos = 0; pos < arr.length; pos++) {
if(arr[pos] == toRemove) {
for(int i = pos + 1; i < arr.length; i++) {
arr[i - 1] = arr[i];
}
arr[arr.length -1] = 0;
return;
}
}
Hi so I am supposed to count the number of unique elements after an array sort excluding duplicates but i'm getting the wrong output.
In in = new In(args[0]);
int[] whitelist = in.readAllInts();
Arrays.sort(whitelist);
int count = 0;
for (int i = 0; i < whitelist.length; i++) {
if (whitelist[i] == whitelist[count]) {
count++;
}
}
while (!StdIn.isEmpty()) {
int key = StdIn.readInt();
rank(key, whitelist);
}
System.out.println(count);
}
}
expected output: java InstrumentedBinarySearch tinyW.txt < tinyT.txt
65
got: 16
Did i count the number of duplicates or something?
int flag = 0;
int count = 0;
for (int i = 0; i < whitelist.length; i++) //Element to be checked for
{
for (int j=0; j< whitelist.length ; j++) //Loop that goes through the whole array
{
if (whitelist[i] == whitelist[j]) //checks if there are duplicates
{
flag++; // count
}
}
if( flag==1) //There should be only 1 instance of the element in the array and that is the element itself
{
System.out.println(whitelist[i]); //displays unique element
count++; // Keeps count
}
}
This algorithm counts how many different unique numbers there are in the array. A number appearing more than once will only count for 1. I am assuming this is what you mean, as opposed to "numbers which appear exactly once".
There is a more trivial way to do it, as proposed in another answer, but it requires a nested for-loop and therefore executes in quadratic complexity. My algorithm below attempts to solve the problem in linear time proportional to the array size.
int uniquesFound = 0;
// Assume that array is sorted, so duplicates would be next to another.
// If we find duplicates, such as 12223, we will only count its last instance (i.e. the last '2')
for (int i = 0; i < whitelist.length; i++) {
// If we are at the last element, we know we can count it
if (i != whitelist.length - 1) {
if (whitelist[i] != whitelist[i+1]) {
uniquesFound++;
}
else {
// Nothing! If they are the same, move to the next step element
}
} else {
uniquesFound++;
}
}
For instance, given the array:
{1,2,3} this will yield 3 because there are 3 unique numbers
{1,2,3,3,3,4,4,4,5} this will yield 5 because there are still 5 unique numbers
First let's take a look at your loop:
for (int i = 0; i < whitelist.length; i++) {
if (whitelist[i] == whitelist[count]) {
count++;
}
}
You should be comparing consecutive elements in the list, like whitelist[0] == whitelist[1]?, whitelist[1] == whitelist[2]?, whitelist[3] == whitelist[4]?, etc. Doing whitelist[i] == whitelist[count] makes no sense in this context.
Now you have two options:
a. Increment your counter when you find two consecutive elements that are equal and subtract the result from the total size of the array:
for (int i = 0; i < whitelist.length - 1; i++) {
if (whitelist[i] == whitelist[i + 1]) {
count++;
}
}
int result = whitelist.length - count;
b. Change the condition to count the transitions between consecutive elements that are not equal. Since you are counting the number of transitions, you need to add 1 to count in the end to get the number of unique elements in the array:
for (int i = 0; i < whitelist.length - 1; i++) {
if (whitelist[i] != whitelist[i + 1]) {
count++;
}
}
int result = count + 1;
Note that, in both cases, we loop only until whitelist.length - 1, so that whitelist[i + 1] does not go out of bounds.
I have to write a method that takes an array of ints that is already sorted in numerical order then remove all the duplicate numbers and return an array of just the numbers that have no duplicates. That array must then be printed out so I can't have any null pointer exceptions. The method has to be in O(n) time, can't use vectors or hashes. This is what I have so far but it only has the first couple numbers in order without duplicates and then just puts the duplicates in the back of the array. I can't create a temporary array because it gives me null pointer exceptions.
public static int[] noDups(int[] myArray) {
int j = 0;
for (int i = 1; i < myArray.length; i++) {
if (myArray[i] != myArray[j]) {
j++;
myArray[j] = myArray[i];
}
}
return myArray;
}
Since this seems to be homework I don't want to give you the exact code, but here's what to do:
Do a first run through of the array to see how many duplicates there are
Create a new array of size (oldSize - duplicates)
Do another run through of the array to put the unique values in the new array
Since the array is sorted, you can just check if array[n] == array[n+1]. If not, then it isn't a duplicate. Be careful about your array bounds when checking n+1.
edit: because this involves two run throughs it will run in O(2n) -> O(n) time.
Tested and works (assuming the array is ordered already)
public static int[] noDups(int[] myArray) {
int dups = 0; // represents number of duplicate numbers
for (int i = 1; i < myArray.length; i++)
{
// if number in array after current number in array is the same
if (myArray[i] == myArray[i - 1])
dups++; // add one to number of duplicates
}
// create return array (with no duplicates)
// and subtract the number of duplicates from the original size (no NPEs)
int[] returnArray = new int[myArray.length - dups];
returnArray[0] = myArray[0]; // set the first positions equal to each other
// because it's not iterated over in the loop
int count = 1; // element count for the return array
for (int i = 1; i < myArray.length; i++)
{
// if current number in original array is not the same as the one before
if (myArray[i] != myArray[i-1])
{
returnArray[count] = myArray[i]; // add the number to the return array
count++; // continue to next element in the return array
}
}
return returnArray; // return the ordered, unique array
}
My previous answer to this problem with used an Integer List.
Not creating a new array will surely result in nulls all over the initial array. Therefore create a new array for storing the unique values from the initial array.
How do you check for unique values? Here's the pseudo code
uniq = null
loop(1..arraysize)
if (array[current] == uniq) skip
else store array[current] in next free index of new array; uniq = array[current]
end loop
Also as others mentioned get the array size by initial scan of array
uniq = null
count = 0
loop(1..arraysize)
if (array[current] == uniq) skip
else uniq = array[current] and count++
end loop
create new array of size count
public static int[] findDups(int[] myArray) {
int numOfDups = 0;
for (int i = 0; i < myArray.length-1; i++) {
if (myArray[i] == myArray[i+1]) {
numOfDups++;
}
}
int[] noDupArray = new int[myArray.length-numOfDups];
int last = 0;
int x = 0;
for (int i = 0; i < myArray.length; i++) {
if(last!=myArray[i]) {
last = myArray[i];
noDupArray[x++] = last;
}
}
return noDupArray;
}
public int[] noDups(int[] arr){
int j = 0;
// copy the items without the dups to res
int[] res = new int[arr.length];
for(int i=0; i<arr.length-2; i++){
if(arr[i] != arr[i+1]){
res[j] = arr[i];
j++;
}
}
// copy the last element
res[j]=arr[arr.length-1];
j++;
// now move the result into a compact array (exact size)
int[] ans = new int[j];
for(int i=0; i<j; i++){
ans[i] = res[i];
}
return ans;
}
First loop is O(n) and so is the second loop - which totals in O(n) as requested.
I am working on a java assignment where I need to delete an integer element in an array and shift the below elements up on space to keep them in order. The array is currently random integers in descending order. I am not allowed to use array.copy because I will need to collect array usage information as part of the assignment. I have tried a ton of different ways of doing this but cannot seem to get it working.
public static void deletionArray(int anArray[], int positionToDelete) {
for (int j = anArray[positionToDelete] - 1; j < anArray.length; j++) {
System.out.println("j is " + j);
anArray[j] = anArray[j + 1];
}
displayArray(anArray);
}
You're iterating until anArray.length (exclusive), but inside the loop, you're accessing anArray[j + 1], which will thus be equal to anArray[anArray.length] at the last iteration, which will cause an ArrayIndexOutOfBoundsException.
Iterate until anArray.length - 1 (exclusive), and decide what should be stored in the last element of the array instead of its previous value.
You're also starting at anArray[positionToDelete] - 1, instead of starting at positionToDelete.
You have two bugs there.
Since this is an assignment, I won't give a complete answer - just a hint. Your loop definition is wrong. Think about this: what happens on the first and on the last iteration of the loop? Imagine a 5-element array (numbered 0 to 4, as per Java rules), and work out the values of variables over iterations of the loop when you're erasing element number, say, 2.
Use System.arraycopy faster than a loop:
public static void deletionArray( int anArray[], int positionToDelete) {
System.arraycopy(anArray, positionToDelete + 1, anArray,
positionToDelete, anArray.length - positionToDelete - 1);
//anArray[length-1]=0; //you may clear the last element
}
public static int[] deletionArray(int anArray[], int positionToDelete) {
if (anArray.length == 0) {
throw new IlligalArgumentException("Error");
}
int[] ret = new int[anArray.length - 1];
int j = 0;
for (int i = 0; i < anArray.length; ++i) {
if (i != positionToDelete) {
ret[j] = anArray[i];
++j;
}
}
return ret;
}
Why do we reserve a new array?
Because if don't, we would use C\C++-style array: an array and a "used length" of it.
public static int deletionArray(int anArray[], int positionToDelete, int n) {
if (n == 0) {
throw new IlligalArgumentException("Error");
}
for (int i = positionToDelete; i < n - 1; ++i) {
anArray[i] = anArray[i + 1];
}
return n - 1; // the new length
}
How's this ? Please note the comment, I don't think you can delete an element in an array, just replace it with something else, this may be useful : Removing an element from an Array (Java)
Updated with 'JB Nizet' comment :
public class Driver {
public static void main (String args []){
int intArray[] = { 1,3,5,6,7,8};
int updatedArray[] = deletionArray(intArray , 3);
for (int j = 0; j < updatedArray.length; j++) {
System.out.println(updatedArray[j]);
}
}
public static int[] deletionArray(int anArray[], int positionToDelete) {
boolean isTrue = false;
for (int j = positionToDelete; j < anArray.length - 1; j++) {
if(j == positionToDelete || isTrue){
isTrue = true;
anArray[j] = anArray[j + 1];
}
}
anArray[anArray.length-1] = 0; //decide what value this should be or create a new array with just the array elements of length -> anArray.length-2
return anArray;
}
}