Is it possible to remove an index from a object array? - java

I have seen you can do this using ArrayLists, but is it possible to do this using a normal object array?
deleting an object from an array [java]
At the start of each the player is given 3 random dice from a cup.
The cup has 13 dice in total.
When the player is given the 3 dice from the cup the cup should have only 10 dice in left. I was trying to set the value to null but this still counts as a index in the array so the length does not change.
// Removing the 3 dice which were picked form the cup of the current player, the diceToTakeOut is a String array with a length of 3 the newTurnCup is a Object array with a length of 13
public static Dice [] cup(String [] diceTotakeOut, Dice [] newTurnCup){
for (int i = 0; i < diceTotakeOut.length; i++) {
if (diceTotakeOut.length > 0) {
if (diceTotakeOut[i] == newTurnCup[i].getName()) {
newTurnCup[i] = null;
}
}
}
return newTurnCup;
}
I have tried a few different ways which I could think of:
newTurnCup[i] = null;
newTurnCup[i] = newTurnCup[i - 1];
The result would be after each turn the array holding the dice would have 3 index less.

It's not doable since the array has a fixed size.
But try using an ArrayList which allow you to remove elements dynamically using the method remove(int index)
or:
shift the content of the array starting from the targeted index to the end. (shift: left to right).

An array variable in Java is a pointer to a zone of memory directly proportionate to it's capacity and the size of the type it contains. This area cannot be dynamically modified. The only way to do what you want is to create a new array variable that has allocated the new size of array you want. This is what happens behind the scenes also in the Collections that implement this functionality just that there are optimisations in place in order to do this (potentially very costly) operations only when it is needed.
So my best suggestion would be to change your design to use Lists, ArrayLists for example. LinkedLists, althought they came out as a nice idea, in practice are generally avoided because they are in fact slower (they don't take advantage of hardware memory caching).

You can't do this cleanly with an array; you would have to recreate a shorter array every time.
You can do it with other data structures, for example a LinkedList.

Since you are working with array and not ArrayList, you can achieve this by creating a work around.
public static Dice[] removeTheElement(Dice[] arr, int index) {
// If the array is empty
// or the index is not in array range
// return the original array
if (arr == null
|| index < 0
|| index >= arr.length) {
return arr;
}
// Create another array of size one less
Dice[] anotherArray = new Dice[arr.length - 1];
// Copy the elements except the index
// from original array to the other array
for (int i = 0, k = 0; i < arr.length; i++) {
// if the index is
// the removal element index
if (i == index) {
continue;
}
// if the index is not
// the removal element index
anotherArray[k++] = arr[i];
}
// return the resultant array
return anotherArray;
}
So in here, we pass as a parameter the Object that we are working with, and the index of the array that we like to remove. We create a temporary Object inside to our function and return it without the element with the index number that we provided.

You can't do that. In Java an array is an immutable object. Once created, the size of this array cannot be changed (sure you could modify array items).
To have a collection with the various size you should use List collection: ArrayList - this is based on an internal array with additional property - size, LinkedList.
List<Dice> dices = new ArrayList<>(); // dices.size() -> 0
dices.add(null); // dices.size() -> 1
dices.add(null); // dices.size() -> 2
dices.remove(0); // dices.size() -> 1
To make array immutability clear, this is an example of how manually remove an item from an array:
public static Dice[] removeItem(Dice[] dices, int i) {
if (dices == null || dices.length == 0)
return dices;
if (i < 0 || i >= dices.length)
throw new ArrayIndexOutOfBoundsException();
Dice[] res = new Dice[dices.length - 1];
System.arraycopy(dices, 0, res, 0, i);
System.arraycopy(dices, i + 1, res, i, dices.length - i - 1);
return res;
}
Dice[] arr = null;
arr = removeItem(arr, 5);

As mentioned in other answers, you cannot remove an element from an array directly. You need to write a custom method which will copy all the elements except the one which you need to remove.
However, I suggest you should use ArrayUtils from Apache Commons.
ArrayUtils.remove(array, index)
Some examples from the docs:
ArrayUtils.remove(["a", "b"], 0) = ["b"]
ArrayUtils.remove(["a", "b"], 1) = ["a"]
Refer: ArrayUtils Documentation

Your best bet is to use ArrayList and then after manipulating getting array out of it.
If you want to get your hands dirty and are accepting that you have to create new array, you can do the following:
private static String[] removeIndex(String[] inputArray, int indexToRemove){
if (indexToRemove >= inputArray.length) {
throw new IndexOutOfBoundsException("index " + indexToRemove + " is not allowed for array with size=" + inputArray.length);
}
String[] resultArray = new String[inputArray.length - 1 ];
System.arraycopy(inputArray, 0, resultArray, 0, indexToRemove);
System.arraycopy(inputArray, indexToRemove + 1, resultArray, indexToRemove, resultArray.length - indexToRemove);
return resultArray;
}
And then consuming it:
String[] inputArray = new String[]{"1","2","3","4","5","6","7","8","9","10"};
System.out.println(Arrays.toString(removeIndex(inputArray, 0)));
System.out.println(Arrays.toString(removeIndex(inputArray, 1)));
System.out.println(Arrays.toString(removeIndex(inputArray, 2)));
System.out.println(Arrays.toString(removeIndex(inputArray, 3)));
System.out.println(Arrays.toString(removeIndex(inputArray, 4)));
System.out.println(Arrays.toString(removeIndex(inputArray, 5)));
System.out.println(Arrays.toString(removeIndex(inputArray, 6)));
System.out.println(Arrays.toString(removeIndex(inputArray, 7)));
System.out.println(Arrays.toString(removeIndex(inputArray, 8)));
System.out.println(Arrays.toString(removeIndex(inputArray, 9)));
System.out.println(Arrays.toString(removeIndex(inputArray, 10)));
produces:
[2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Exception in thread "main" java.lang.IndexOutOfBoundsException: index 10 is not allowed for array with size=10
at Scratch.removeIndex(scratch.java:81)
at Scratch.main(scratch.java:73)

Related

Union of two array, but time complexity is the issue

Multiple solutions available online for union of arrays, I came up with one of my own which is working fine but again it has significant time complexities (which I obviously don't know). So in order to use similar logic in a better way I am asking here. Any suggestion would be great!
Initially there are two arrayList with different sizes and numbers in it.
First step is to append both of them in a single List
Second step is to sort the new array using Collections.sort()
method.
Third is to use .remove() to remove the duplicates from it.
Below is the code
//initial two arrays
array1[0, 2, 3, 4, 5] and array2[0, 1, 2, 3, 5, 7, 8]
//for loop to append them in one arrayList and sort
for(k = 0; k< array1.size();k++){
array3.add(array1.get(k));
}
for(k = 0; k< array2.size();k++){
array3.add(array2.get(k));
}
Collections.sort(array3);
//Now removing the duplicates
for(k=0; k<array3.size();k++){
if(k != array3.size()-1){
if(Objects.equals(array3.get(k), array3.get(k + 1))){
array3.remove(k);
}
}
}
You can do this optimally via hash sets
int[] array1 = {0, 2, 3, 4, 5};
int[] array2 = {0, 1, 2, 3, 5, 7, 8};
HashSet<Integer> union = new HashSet<>();
for (int element : array1) {
union.add(element);
}
// Add all the elements of the second array to the HashSet
for (int element : array2) {
union.add(element);
}
this solution does not guarantee the order of the elements in the union set.
IntStream.distinct
You can use distinct() operation, which maintains a LinkedHashSet under the hood to guarantee uniqueness of elements and preserve their order, to obtain the union of the given arrays:
int[] array1 = {0, 2, 3, 4, 5};
int[] array2 = {0, 1, 2, 3, 5, 7, 8};
int[] union = IntStream
.concat(Arrays.stream(array1), Arrays.stream(array2))
.distinct().toArray();
System.out.println(Arrays.toString(union));
Output:
[0, 2, 3, 4, 5, 1, 7, 8]

Find minimum peak elements in an array

Question: Given an array numbers = {2, 7, 8, 5, 1, 6, 3, 9, 4}. Check the below conditions, both the conditions should be satisfied.
a[i] > a[i-1] or if first element a[i] > a[i+1]
a[i] > a[i+1] or if last element a[lastelement] > a[lastelement - 1]
Therefore:
1st Iteration - 8, 6, 9 are peak values. Remove the smallest ele. Remove 6. New arr {2, 7, 8, 5, 1, 3, 9, 4}. Output Arr - {6}
2nd Iteration - 8, 9 are peak values. Remove the smallest ele. Remove 8. New arr {2, 7, 5, 1, 3, 9, 4}. Output Arr - {6, 8}
3rd Iteration - 7, 9 are peak values. Remove the smallest ele. Remove 7. New arr {2, 5, 1, 3, 9, 4}. Output Arr - {6, 7, 8}
4th Iteration - 5, 9 are peak values. Remove the smallest ele. Remove 5. New arr {2, 1, 3, 9, 4}. Output Arr - {6, 7, 8, 5}
5th Iteration - 2, 9 are peak values. Remove the smallest ele. Remove 2. New arr {1, 3, 9, 4}. Output Arr - {6, 7, 8, 5, 2}
6th Iteration - 9 are peak values. Remove the smallest ele. Remove 9. New arr {1, 3, 4}. Output Arr - {6, 7, 8, 5, 2, 9}
7th Iteration - 4 are peak values. Remove the smallest ele. Remove 4. New arr {1, 3}. Output Arr - {6, 7, 8, 5, 2, 9, 4}
8th Iteration - 3 are peak values. Remove the smallest ele. Remove 3. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3}
9th Iteration - 1 are peak values. Remove the smallest ele. Remove 1. New arr {1}. Output Arr - {6, 7, 8, 5, 2, 9, 4, 3, 1}
Output: {6, 8, 7, 5, 2, 9, 4, 3, 1}
My solution is working but I am looking for optimized solution. Please let me know.
Here is my code:
public int[] findMinimumPeaks(int[] arr){
List<Integer> list1 = new ArrayList<Integer>(arr.length);
int[] output = new int[arr.length];
for(int i: arr)
list1.add(i);
for(int i =0; i<arr.length; i++){
int minIndex = minimumPeakElement(list1);
output[i] = list1.get(minIndex);
list1.remove(minIndex);
}
return output;
}
public int minimumPeakElement(List<Integer> list1){
int minIndex = 0, peakStart = Integer.MAX_VALUE, peakEnd = Integer.MAX_VALUE;
int peak = Integer.MAX_VALUE, minPeak = Integer.MAX_VALUE;
if(list1.size() >= 2){
if(list1.get(0) > list1.get(1)) peakStart = list1.get(0);
if(list1.get(list1.size() - 1) > list1.get(list1.size() - 2)) peakEnd = list1.get(list1.size() - 1);
if(peakStart < peakEnd){
minPeak = peakStart;
minIndex = 0;
}
else if(peakEnd < peakStart){
minPeak = peakEnd;
minIndex = list1.size() - 1;
}
}
for(int i=1; i<list1.size() - 1; i++){
if(list1.get(i) > list1.get(i + 1) && list1.get(i) > list1.get(i-1)) peak = list1.get(i);
if(peak < minPeak){
minPeak = peak;
minIndex = i;
}
}
return minIndex;
}
Here is an idea how to optimize asymptotic complexity.
Use single pass over elements of your initial array to split it into "up-down" "slopes" or "hills", i.e. subsequence of elements in ascending order, followed by subsequence in descending order.
Store these slopes in the following datastructure:
val slopes = MinPriorityQueue<Slope>()
class Slope(
var first: Int, // first element of the slope
var last: Int, // last element of the slope
var peak: Int, // max or peak element
var els: MaxPriorityQueue<Int>(), // all elements of the slope
var prev: Slope?, // link to the previous slope in the list or null if first
var next: Slope? // link to the next slope in the list or null if last
)
Slopes should be comparable by their peak value.
Now, having this data structure, you can poll the slope that has minimal peak value in O(log(N)). After you polled the slope, you should update the slope by removing it's peak element (i.e. poll els, then update first, last, peak), also, slope might become eligible to be merged with the previous or next slope:
Admittedly, this solution is not an easy one, having a lot of things to maintain and large number of corner cases. However, it's much better in terms of asymptotic complexity.
Initial data structure build: O(n log(n))
Polling elements while maintaining slopes: O(n log (n))
Overall complexity: O(n log(n))
Notes:
One of the corner cases, if array can have duplicate elements, then inner priority queue (els) becomes MaxPriorityQueue<Pair<Int,Int>>, i.e. you need to store the number of potentially duplicate elements along with the element value.
MinPriorityQueue and MaxPriorityQueue is an abstract heap-based data structure with min and max element at the head respectively. Can be implemented with PriorityQueue in java

Logic to remove first n elements from an array

One of the methods that I need to write for an assignment is supposed to remove the first n elements from an array. However, I am not getting the correct output. I believe I'm having an off by one error, but I am not exactly sure how to fix it.
Solutions should try to maintain the format of the code as closely as possible.
for (int i = n; i >= 0; i--) {
elementData[i] = elementData[i + 1];
size--;
}
What the code is saying is that, for every element n and below, replace it with whatever is in the index higher than it. Then reduce the size variable for every time that you do this, which should result in it looking like a remove operation when printed.
I expected the output of [0, 1, 2, 4, 6, 4, 7] to be [4, 7].
However, I got [7].
n is passed as 5 in the above case.
I realize this is an assignment question looking for an implementation, but anyone doing this in Java should use the provided APIs. For example:
public int[] trimArray(int[] source, int trimBy) {
if (trimBy > source.length) return source;
return Arrays.copyOfRange(source, trimBy, source.length);
}
trimArray(new int[]{0, 1, 2, 4, 6, 4, 7}, 5) // -> [4, 7]
You can just use this:
int[] result = new int[elementData.length - n];
for (int i = 0; i < result.length; i++) {
result[i] = elementData[n + i];
}
Which is an extended form of this:
int[] result = new int[elementData.length - n];
System.arraycopy(elementData, n, result, 0, result.length);
You can use filter:
let a = [0, 1, 2, 4, 6, 4, 7]
you want to obtain [4, 7] removing 5 first elements so type
a = a.filter((_, i) => i >= 5)
Now
a = [4, 7]
elementData = Arrays.copyOfRange( elementData, n, elementData.length ); // originalArray, startIndex, end

find first index in array value greater than x in O(1)

I have a sorted array of type int. I want get the first index whose value is greater than a target in O(1), in java.
eg: int arr[]= {1,4,7,9,15,30}
target= 10
my function should return 4,index of 15.
In order to be able to find the index of a value that has a specific property (ex: is greater than a target) through an array, you must traverse the array implementing search algorithms.
Therefore O(1) is not possible to achieve.
If the array is sorted, as you present it in your example, you are able to achieve what you want in O(log(n)) by implementing binary search algorithm. You may also use the implementation in java.util.Arrays.
If the array is not sorted, you must go through all the elements of the array in a worst case scenario using linear search algorithm with an O(n) complexity.
If you prepare an indices array (or map) like this.
int[] a = {1,4,7,9,15,30};
// prepare indices array
int[] indices = new int[a[a.length - 1] + 1];
for (int i = 0, j = 0, aLength = a.length; i < aLength; ++i)
while (j <= a[i])
indices[j++] = i;
System.out.println(Arrays.toString(indices));
// -> [0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
// get the first index whose value is greater than a target in O(1)
System.out.println(indices[10]); // -> 4 (index of 15)
You can get the index value by indices[target] in O(1).

find unique elements from sorted array with complexity < O(n) [duplicate]

This question already has answers here:
Finding unique numbers from sorted array in less than O(n)
(5 answers)
Closed 8 years ago.
An interveiewer asked me below question:
Search out unique integer values(approx. 1000) from a sorted array of billion records(like 1,1,1,1,3,3,3,4,5,5,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8...........) with complexity less than O(n).
NOTE: NOt to use SET.
One solution that i tried to implement:
Divide that array into two set of arrays,then iterate both subarrays and search in hashmap if element doesnot exit,then add it into hashmap otherwise move to next iteration.
public static void main(String[] args) {
int arr[] = {1,2,4,9,-3,5,6,3,6,12,5,6,2,-1,-3,6,87,9,2,3,5,7,9,1,0,1,3,5,7,6,3,8,6,3,21,45,6};
int size1 =0, size2 = 0;
HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
System.out.println("length of Array:"+arr.length);
if((arr.length)%2 == 0){
size1 = size2 = arr.length/2;
}else{
size1 = (arr.length + 1)/2;
size2 = (arr.length)/2;
}
for(int i=0;((size1-i-1)>= 0)||((size2+i)<(arr.length - 1));i++){
if(map.containsKey(arr[size1 -i-1])== false){
map.put(arr[size1 -i-1],arr[size1 -i-1]);
}
if(map.containsKey(arr[size2 + i]) == false){
map.put(arr[size2 + i], arr[size2 + i]);
}
}
System.out.println(map.keySet());
}
And its working as expected, then he asked what if we divide the array into n sets?
then the complexity would be O(1) or O(n/n)? Is it possible?
Please suggest if there is another way to implement the same without using hashmap?
I'd try a binary search based approach, start from the middle element - if it's identical to one of the edges, then you can use the fact the array is sorted and eliminate that half. If it's different from each of the ones on the edges - divide the array into halves and proceed on each of them recursively.
This is still O(n) in the worst case, but on average it may be better then passing over the entire array (especially if there are many repetitions)
example -
1 1 1 1 1 2 2 2 2
could be done in two steps
why don't you use a Set instead of Map. Anyways, Set does not allow duplicate elements.
public static void main(String[] args) {
int arr[] = { 1, 2, 4, 9, -3, 5, 6, 3, 6, 12, 5, 6, 2, -1, -3, 6, 87,
9, 2, 3, 5, 7, 9, 1, 0, 1, 3, 5, 7, 6, 3, 8, 6, 3, 21, 45, 6 };
Set<Integer> aset = new HashSet<Integer>();
System.out.println("length of Array:" + arr.length);
for (int i : arr) {
aset.add(i);
}
System.out.println(aset);
}

Categories