Remove "hole" in array after remove item - java

I need to delete some objects from an array if they meet a condition.
After removing the object from the array I need the array to have no "holes", meaning I need to shrink the array: not the array size, but reducing the number of objects it contains.
It's okay if there are null values at the end of the array after removing objects.
Which would be more efficient?
Copying the array into new array
Iterating over the array and shift the elements over the "hole" created by removing an object
I must use an array, I cannot use a List implementation.

Use an ArrayList, this will allow you to dynamically change the size of your structure.

If you don't want to use ArrayList yuor solution is fine. But instead of copying your array, create a new empty one with the size of your array and then populate it in a for loop.

1) You can swap deleted element with the last element and make something like size--
2) If you can't swap you have to use System.arraycopy(...) method multiple times to copy parts of array to new array.
public static Object[] deleteElement(Object[] oldArray, int position) {
Object[] newArray = new Object[oldArray.length - 1];
System.arraycopy(oldArray, 0, newArray, 0, position);
System.arraycopy(oldArray, position + 1, newArray, position, newArray.length - position);
return newArray;
}

Based on your requirements,
i need that my array will be without any "holes" so i need to "shrink" that Array,
you must create a new array and move the remaining objects to it. Arrays are a fixed-size construct. You cannot "shrink" an array. You can only allocate new memory and move the elements to the new array.
EDIT: You should alter your question to include the information about allowing null at the end of the array. In that case, moving the elements back 1 index would be better since it eliminates memory allocation (which is expensive) and will have on average n/2 operations (assuming random removal) as opposed to n.

Both of your solutions are O(N) complexity, except the first one require another O(N) memory space. So the second one is slightly better if you really required to work on Array.
If you're working on an array of element that require frequent add and remove in the middle, I would suggest you use Linked-List implementation, so that it can give you constant time of adding and removing any element in your array.

Here's a simple example using System.arraycopy:
Integer[] i1 = new Integer[] {1, 2, 3, 4, 5};
Integer[] i2 = new Integer[4];
// Copy everything, except the third value of i1:
System.arraycopy(i1, 0, i2, 0, 2);
System.arraycopy(i1, 3, i2, 2, 2);
for (int j : i2)
{
System.out.println(j);
}

Some pseudocode
Step 1: Find all the objects from the array that match whatever you want it to match and overwrite them with a unique value (for example: if your array only contains integers 0 or higher, overwrite the ones you want to remove with -1)
Step 1.5: keep a counter of the AMOUNT of removes you did
Step 2: Create a new array with the size of (oldarray.size - counterFromStep1.5)
Step 3: for each non-empty element in oldarray THAT IS NOT (the remove integer), add it to new array

Related

Adding two integer arrays

I have done some searching for this, however I haven't found anything specific to what I'm working on.
I'm trying to do addition with two arrays of integers. This alone isn't difficult, however, I'm having difficulty with a specific aspect.
The array size and array elements are determined by user input. Each digit must be greater than or equal to 0 and less than or equal to 9. The problem lies in the fact that if I initialize an array in my method, I must determine the size of the array when I initialize it. But if the user enters a series of numbers, such as 8, 0, 0, 0 for the first array, and 3, 0, 0, 0 for the second array, that would result in the sum[] being one integer bigger than either of the arrays initialized by the user. I don't want to do
int[] sum = new int[x.length+1]
because in the case of it not needing an extra element, I will get an ugly 0 where I don't want to see that. I'm not necessarily asking for a direct answer with code, but perhaps a bit of wisdom that will push me in the right direction. Thanks.
public static int[] addArrays(int[] x, int[] y){
int[] sum = new int[?];
int carryOver = 0;
int singleDigit = 0;
Just make the array originally the same size as the original (int[] sum = new int[x.length];. Then, if you need to expand the size of your array, set sum =Arrays.copyOf(sum, sum.length+1);, which will expand the size of your array to the necessary size.

add elements from one array to "empty array"

I'm new to arrays in java, so my question might seem simple to all of u
I have two arrays:
int[] newarray = new int[] {1,2,3,4}
int[] result = new int[4] // array with space for 4 elements
i=0
My question is: How do I add elements from newarray to result? For example, how do i add newarray[i]? There seems to be no add function like in python unless you use ArrayLists. Also is it possible to add elements from an array to an arraylist, or doesn't they work together? Hope to get some clarification :)
To set the ith element in result to the ith element in newarray, do the following:
result[i] = newarray[i];
In addition, you can copy over the entirety of the array using arraycopy:
System.arraycopy(newarray, 0, result, 0, newarray.length);
See also:
Arrays - The Java™ Tutorials
arraycopy() in Java
Use System.arrayCopy to copy arrays. Example:
System.arraycopy(newarray, 0, result, 0, newarray.length)
The first argument is the source array, then the source position, then the destination array and destination position, and the length.
int[] newarray = new int[] {1,2,3,4}
int[] result = new int[newarray.length];
for(int i=0;i<newarray.length;i++)
result[i]=newarray[i];
Lets say you want to assign the third value in newarray to the third index in result.
That would be like:
result[2] = newarray[2]
System.arraycopy(newarray, 0, result, 0, newarray.length);
or you can do it manually
for(int i = 0; i < newarray.length; i++) {
result[i] = newarray[i];
}
to work with Arrays, you can use
Arrays.asList(Object[] a);
Either copy elements one at a time in a loop or use System.arraycopy.
Understand that an array in Java is like an array in C in that it's fixed length (there are other classes like ArrayList for variable-length use). So you don't "add" a new element, you simply assign a value (x[i] = something;) to an existing element (which was initialized to zero when the array was created).
To my knowledge there's no "add all elements of this array" method on ArrayList, so to do that you'd have to loop through the array and add the elements one at a time. There are methods to go the other direction.
This should also work:
Arrays.asList(result).addAll(Arrays.asList(newarray));
Returns a fixed-size list backed by the specified array. (Changes to
the returned list "write through" to the array.)
Using static imports:
asList(result).addAll(asList(newarray));

In java, what is the best way to sort an integer array if only the last number item is displaced?

It's an array of integers.
It was created this way:
No element is repeated. Every time an element is added, its number is the next available integer, from 0 onwards. This way, if you add 6 elements in a row, they will be 0, 1, 2, 3, 4, 5, in that order. If you delete an element, the array shrinks, and a 'hole' is left between two of the elements, they are no longer consecutive because of that gap: 0, 1, 3, 4, 5. Then comes the problem: if you add a new element, it gets added to the end, but has the next available integer. So, the array is now 0, 1, 3, 4, 5, 2. It needs to be sorted, so the 2 can occupy its place between the 1 and the 3.
What is the best way to do it? I have thought of several methods. The list is nearly ordered, and it has the property that, when it is ordered, every element is equal to or greater than its index in the array. I am currently doing a bubble sort (don't laugh), i think quick sort is overkill, i dont want to go recursive or use temporary arrays, and i dont want to change the add-element method (which adds the element at the end), so it must be sorted immediately after adding an element (so only the last element is out of place)
Take the last element and do a insertion sort.
Maybe you should look at the idea of Insertion Sort.
You do not need to sort the whole list, just insert the last element in order:
int pos = array.length - 1:
while (pos > 0 && array[pos] < array[pos - 1]) {
tmp = array[pos - 1];
array[pos - 1] = array[pos];
array[pos] = tmp;
pos--;
}
What about using a java.util.BitSet instead? You'd get constant-time insertion and removal (finding the first free place will still take O(n) though). And with nextSetBit, you can iterate over the set in ascending order. With nextClearBir(), finding the first unused index becomes trivial, too.
//based on gpeche's code
int pos = array.length - 1;
int val = array[pos];
while (pos > 0 && array[pos-1] > val) {
array[pos] = array[pos - 1];
pos--;
}
array[pos] = val;
Are you constrained to use an array? If not, then just use a TreeSet. Why write your own sort algorithm when you can make use of standard libraries that perform this function already? It has guaranteed O(log(n)) time for insertions.
import java.util.TreeSet;
TreeSet<Integer> sortedSet = new TreeSet<Integer>();
// Add integers as needed
sortedSet.add( someInt );
// If you need an array at the end
Integer[] array = sortedSet.toArray( new Integer[sortedSet.size()] );

How does this Java code work?

public static void main(String[] args)
{
int [][]shatner = new int[1][1];
int []rat = new int[4];
shatner[0] = rat;
System.out.println(shatner[0][3]);
}
surprised, The output is 0, why Java doesn't check this kind of indexOutOfBound error?
Don't be surprised. shatner[0] is an array (rat) and happens to be of length 4. So shartner[0][3] is rat[3] which happens to be 0..
Where do you see an "indexOutOfBound error"? The code does the following:
Initalize an array (size 1) of int arrays (size 1), i.e. a 2D array, contents are intialized with 0
Initalize a array of int, size 4, content is intialized with 0
set the single element of the 2D array to the size 4 1D array
access the last element of the first array in the 2D array, which is 0
There is nothing going out of bounds.
The 0th row in the shatner array gets reinitialized to int[4].
There is no index out of bounds error. shatner is an array of arrays. You replaced the first array of length one with a new one of length four. So now shatner[0][3] is a perfectly legit place in memory.
It's not that Java doesn't check the IndexOutOfBoundsException. It's that the answer SHOULD be zero. The key line is
shatner[0] = rat;
Since that means that the 0th index of shatner is pointing to an array of length 4, shatner[0][4] is totally valid.
I'm thinking it's because java's arrays are working a bit differently than expected. You initialize shatner to [1][1], meaning something like, {{0},{0}} in memory.
However, you then assign an integer to the first element, turning it into {{0,0,0,0},{0}} in memory, so Java is addressing the newly assigned index.
Arrays need not be rectangular in Java. This is a jagged array and is perfectly fine.

Why does this code throw an IndexOfOutBoundsException - aka, what's up with ensureCapacity()?

Consider the following two snippets of code:
int index = 676;
List<String> strings = new ArrayList<String>();
strings.add(index, "foo");
and
int index = 676;
List<String> strings = new ArrayList<String>();
strings.ensureCapacity(index);
strings.add(index, "foo");
In the first case, I'm not surprised to see an IndexOfOutBoundsException. According to the API, add(int index, E element) will throw an IndexOfOutBoundsException "if the index is out of range (index < 0 || index > size())". The size of strings is 0 before any elements have been added, so index will definitely be larger than the ArrayList's size.
However, in the second case, I would expect the call to ensureCapacity to grow strings such that the call to add would correctly insert the string "foo" at index 676 - but it doesn't.
Why not?
What should I do so that add(index, "foo") works for index > strings.size()?
The capacity of the underlying array in an ArrayList is distinct from the higher-level List API methods (add, remove, etc.), and only speaks to the size of the backing array. If you want to allow adding elements beyond the list bounds, you'll need to code that yourself (or find a collection that does it for you) in a utility class, populating nulls, empty objects, or whatever your application expects between the new index and the old size.
ArrayList.ensureCapacity() does not change the actual size of the list (which is returned by size()), but rather reallocate the internal buffer such that it will not need to reallocate the buffer to grow to this size (when you call list.add(object).
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*/
Taking a wild guess, I think what you're looking for is
Integer index = Integer.valueOf(676);
Map<Integer,String> strings = new HashMap<Integer,String>();
strings.put(index, "foo");
your length is 676, but you have to remember that they are zero based, so in reality, you'd want index -1 would be your max number.

Categories