Implementing ArrayList add Method manually using arrays of objects [duplicate] - java

This question already has answers here:
How to add an element at the end of an array?
(6 answers)
Closed 6 years ago.
Hello i need to manually implement an arraylist.add() method using nothing but arrays and an array copy method but im having trouble doing it . The specification of the method is that the method inserts an element at a specified position and shifts any of the elements currently in the position to the right and add one to the indices expanding the size of the array by one so all elements fit . Someone please help .
private Object [] list;
final int maxObjects = 100;
public ListOfObjects()
{
list= new Object[maxObjects];
}
public ListOfObjects(Object[]o)
{
list= o;
}
public void add(Object element,int index)
{
Object[] newData = new Object[list.length+1];
for(int i =0; i < index; i++)
{
newData[i] = list[i];
newData[list] = element;
}
for(int i = index; i < list.length; i++)
{
newData[i+1] = list[i];
}
}

Adding an element to an index of an Object array,
Object[] myObjects;
public static void addObject(Object obj, int index) {
// Assuming you want something in your empty array
if(myObjects == null) {
myObjects = new Object[] { obj };
return;
}
ArrayList<Object> temp = new ArrayList<Object>();
for(int i = 0; i < myObjects.length; i++) {
if(i == index)
temp.add(obj);
temp.add(myObjects[i]);
}
myObjects = temp.toArray(new Object[temp.size()]);
}

The javadoc of System.arrayCopy speaks specifically to the case of the src and dest being the same array:
If the src and dest arguments refer to the same array object, then the
copying is performed as if the components at positions srcPos through
srcPos+length-1 were first copied to a temporary array with length
components and then the contents of the temporary array were copied
into positions destPos through destPos+length-1 of the destination
array.
If your backing list is of sufficient size, then you simply need to use arrayCopy to move the affected indexes over 1.
//shift everything after the index over
System.arrayCopy(list, index, list, index + 1, list.length - index);
//place new value in index
list[index] = element;
Otherwise you need to create a new array, then use arrayCopy to copy everything before the inserting index.
Object[] newList = new Object[calcSize()];
//first copy everything before index if index is not 0
if (index > 0)
{
System.arrayCopy(list, 0, newList, 0, index);
}
newList[index] = element;
System.arrayCopy(list, index, newList, index+1, list.length - index);

You logic looks wrong to me. You should do something like -
Object[] newData = new Object[list.length+1];
for(int i =0; i < index; i++)
{
newData[i] = list[i];
}
newData[index] = element;
for(int i = index; i < list.length; i++)
{
newData[i+1] = list[i];
}

This solution takes advantage of the ArrayList iterator, which returns objects in the proper sequence:
ArrayList<Object> elementInserter(ArrayList<Object> inArray, Object element, int index){
ArrayList<Object> outArray = new ArrayList<Object>(inArray.size() + 1);
outArray.addAll(inArray.subList(0, index));
outArray.add(element);
outArray.addAll(inArray.subList(index, inArray.size()));
return outArray;
}

Related

Reverse a linkedList from a array

I am trying to add a reverse linked list back to a linked list from an array.
public void reverse(){
//Calling function to take a linked list and put it inside an array
int[] myArray = this.toArray();
//Populate list using array
for (int i= 0; i < myArray.length; i++){
this.addHead(myArray[i]);
}
System.out.println(this.toString());
}
Here is my method this works fine but it only set the linked list to the last index and stops.
EX.
[1,7,7,6]
lS.reverse()
=> [6]
Here is the to array function
//Return int array of list values
public int[] toArray(){
//Creating a array of the size of linkedList
//New copy of head
int f[] = new int[this.size()];
Node newHead = head;
int arrayIndex = 0;
while(newHead != null){
//Set the current Index to the data at head location
f[arrayIndex] = newHead.data();
//Moves the head to next postion
newHead = newHead.next();
//Increment index
arrayIndex = arrayIndex + 1;
}
return f;
}
The result I am looking to acheive is after reverse() is called I will get from
[1,7,7,6]
To A linked list
6,7,7,1
Don't know what you are trying to achieve, but if the initial list is given, there is no need for an array conversion. You can implement something along these lines:
public <T> List<T> reverseList( List<T> list )
{
List<T> newList = new ArrayList<T>();
for( int i = 0; i < list.size(); i++ )
{
newList.add( list.get( list.size() - ( i + 1 ) ) );
}
return newList;
}
If arrays are absolutely needed for some reason, you can use this analogously. Create an array, fill up by reversing index order.

Changing 2D ArrayList code to 2D array code

I found this code online and it works well to permute through the given array and return all possible combinations of the numbers given. Does anyone know how to change this code to incorporate a 2D array instead?
public static ArrayList<ArrayList<Integer>> permute(int[] numbers) {
ArrayList<ArrayList<Integer>> permutations = new ArrayList<ArrayList<Integer>>();
permutations.add(new ArrayList<Integer>());
for ( int i = 0; i < numbers.length; i++ ) {
ArrayList<ArrayList<Integer>> current = new ArrayList<ArrayList<Integer>>();
for ( ArrayList<Integer> p : permutations ) {
for ( int j = 0, n = p.size() + 1; j < n; j++ ) {
ArrayList<Integer> temp = new ArrayList<Integer>(p);
temp.add(j, numbers[i]);
current.add(temp);
}
}
permutations = new ArrayList<ArrayList<Integer>>(current);
}
return permutations;
}
This is what I have attempted:
public static int[][] permute(int[] numbers){
int[][] permutations = new int[24][4];
permutations[0] = new int[4];
for ( int i = 0; i < numbers.length; i++ ) {
int[][] current = new int[24][4];
for ( int[] permutation : permutations ) {
for ( int j = 0; j < permutation.length; j++ ) {
permutation[j] = numbers[i];
int[] temp = new int[4];
current[i] = temp;
}
}
permutations = current;
}
return permutations;
}
However this returns all zeroes. I chose 24 and 4 because that is the size of the 2D array that I need.
Thanks
It’s not really that easy. The original code exploits the more dynamic behaviour of ArrayList, so a bit of hand coding will be necessary. There are many correct thoughts in your code. I tried to write an explanation of the issues I saw, but it became too long, so I decided to modify your code instead.
The original temp.add(j, numbers[i]); is the hardest part to do with arrays since it invloves pushing the elements to the right of position j one position to the right. In my version I create a temp array just once in the middle loop and shuffle one element at a time in the innermost loop.
public static int[][] permute(int[] numbers) {
// Follow the original here and create an array of just 1 array of length 0
int[][] permutations = new int[1][0];
for (int i = 0; i < numbers.length; i++) {
// insert numbers[i] into each possible position in each array already in permutations.
// create array with enough room: when before we had permutations.length arrays, we will now need:
int[][] current = new int[(permutations[0].length + 1) * permutations.length][];
int count = 0; // number of new permutations in current
for (int[] permutation : permutations) {
// insert numbers[i] into each of the permutation.length + 1 possible positions of permutation.
// to avoid too much shuffling, create a temp array
// and use it for all new permutations made from permutation.
int[] temp = Arrays.copyOf(permutation, permutation.length + 1);
for (int j = permutation.length; j > 0; j--) {
temp[j] = numbers[i];
// remember to make a copy of the temp array
current[count] = temp.clone();
count++;
// move element to make room for numbers[i] at next position to the left
temp[j] = temp[j - 1];
}
temp[0] = numbers[i];
current[count] = temp.clone();
count++;
}
assert count == current.length : "" + count + " != " + current.length;
permutations = current;
}
return permutations;
}
My trick with the temp array means I don’t get the permutations in the same order as in the origianl code. If this is a requirement, you may copy permutation into temp starting at index 1 and shuffle the opposite way in the loop. System.arraycopy() may do the initial copying.
The problem here is that you really need to implement properly the array version of the ArrayList.add(int,value) command. Which is to say you do an System.arraycopy() and push all the values after j, down one and then insert the value at j. You currently set the value. But, that overwrites the value of permutation[j], which should actually have been moved to permutations[j+1] already.
So where you do:
permutation[j] = numbers[i];
It should be:
System.arraycopy(permutation,j, permutations, j+1, permutations.length -j);
permutation[j] = numbers[i];
As the ArrayList.add(int,value) does that. You basically wrongly implemented it as .set().
Though personally I would scrap the code and go with something to dynamically make those values on the fly. A few more values and you're talking something prohibitive with regard to memory. It isn't hard to find the nth index of a permutation. Even without allocating any memory at all. (though you need a copy of the array if you're going to fiddle with such things without incurring oddities).
public static int[] permute(int[] values, long index) {
int[] returnvalues = Arrays.copyOf(values,values.length);
if (permutation(returnvalues, index)) return returnvalues;
else return null;
}
public static boolean permutation(int[] values, long index) {
return permutation(values, values.length, index);
}
private static boolean permutation(int[] values, int n, long index) {
if ((index == 0) || (n == 0)) return (index == 0);
int v = n-(int)(index % n);
int temp = values[n];
values[n] = values[v];
values[v] = temp;
return permutation(values,n-1,index/n);
}

Finding how many different values there are in an array

Let's say I have an array in the length of n, and the only values that can appear in it are 0-9. I want to create a recursive function that returns the number of different values in the array.
For example, for the following array: int[] arr = {0,1,1,2,1,0,1} --> the function will return 3 because the only values appearing in this array are 0, 1 and 2.
The function receives an int array and returns int
something like this:
int numOfValues(int[] arr)
If you are using Java 8, you can do this with a simple one-liner:
private static int numOfValues(int[] arr) {
return (int) Arrays.stream(arr).distinct().count();
}
Arrays.stream(array) returns an IntStream consisting of the elements of the array. Then, distinct() returns an IntStream containing only the distinct elements of this stream. Finally, count() returns the number of elements in this stream.
Note that count() returns a long so we need to cast it to an int in your case.
If you really want a recursive solution, you may consider the following algorithm:
If the input array is of length 1 then the element is distinct so the answer is 1.
Otherwise, let's drop the first element and calculate the number of distinct elements on this new array (by a recursive call). Then, if the first element is contained in this new array, we do not count it again, otherwise we do and we add 1.
This should give you enough insight to implement this in code.
Try like this:
public int myFunc(int[] array) {
Set<Integer> set = new HashSet<Integer>(array.length);
for (int i : array) {
set.add(i);
}
return set.size();
}
i.e, add the elements of array inside Set and then you can return the size of Set.
public int f(int[] array) {
int[] counts = new int[10];
int distinct = 0;
for(int i = 0; i< array.length; i++) counts[array[i]]++;
for(int i = 0; i< counts.length; i++) if(counts[array[i]]!=0) distinct++;
return distinct;
}
You can even change the code to get the occurrences of each value.
You can try following code snippet,
Integer[] arr = {0,1,1,2,1,0,1};
Set<Integer> s = new HashSet<Integer>(Arrays.asList(arr));
Output: [0, 1, 2]
As you asked for a recursive implementation, this is one bad way to do that. I say bad because recursion is not the best way to solve this problem. There are other easier way. You usually use recursion when you want to evaluate the next item based on the previously generated items from that function. Like Fibonacci series.
Ofcourse you will have to clone the array before you use this function otherwise your original array would be changed (call it using countDistinct(arr.clone(), 0);)
public static int countDistinct(int[] arr, final int index) {
boolean contains = false;
if (arr == null || index == arr.length) {
return 0;
} else if (arr.length == 1) {
return 1;
} else if (arr[index] != -1) {
contains = true;
for (int i = index + 1; i < arr.length; i++) {
if (arr[index] == arr[i]) {
arr[i] = -1;
}
}
}
return countDistinct(arr, index + 1) + (contains ? 1 : 0);
}
int numOfValues(int[] arr) {
boolean[] c = new boolean[10];
int count = 0;
for(int i =0; i < arr.length; i++) {
if(!c[arr[i]]) {
c[arr[i]] = true;
count++;
}
}
return count;
}

I do not want to change the array inside the method [duplicate]

This question already has an answer here:
Java Arrays.sort(test) sorts two arrays
(1 answer)
Closed 9 years ago.
when I put an array inside my method public int[] insertionSort(final int array[])
I do not change the array[]
public int[] insertionSort(final int array[]) {
int[] array_for_sorting = array;
final int[]TempArray = array;
int n = array_for_sorting.length;
// printNumbers(TempArray);
for (int j = 1; j < n; j++) {
int key = array_for_sorting[j];
int i = j-1;
while ( (i > -1) && ( array_for_sorting [i] > key ) ) {
array_for_sorting [i+1] = array_for_sorting [i];
i--;
}
array_for_sorting[i+1] = key;
// printNumbers(array_for_sortying);
}
//array = TempArray;
printNumbers(TempArray);// for printing
return array_for_sorting;
}
also, why my TempArray change after the for loop ?
All your array references (array, array_for_sorting, TempArray) are referring the same array object. So, when you modified the array content, it will visible from all its reference.
What does final means here, You can't reassign another array to a final array reference. But, its content can be altered
If you need to copy a arrays, use Arrays.copyOf(array, array.length);
Actually the TempArray and array are two referances to same location in memory, so you are modifying the TempArray when you modify the array
So you need to create a new array like, u can use :
System.arraycopy(array, 0, TempArray, 0, array.length );
Then modify the Array and another array will not change.

how to delete array elements

Write a method deleteElement which takes as input an int[] and an int target and deletes all occurrences of target from the array. The method should return the newint[]
. Question to consider:
Why is it that we have to return an array and can't simply change the input parameter array?
public class warm5{
public static void main(String[] args){
int[] array1= {1,2,2,3,4,5,2};
int target1 = 2;
deleteElement(array1,target1);
public static int[] deleteElement(int[] array, int target){
for(int i = 0, i<array.length, i++){
if(array1[i] == target){
}
}
}
}
}
Here is what i wrote, im not sure how to continue it to remove the 2's in the array.
please help!
You can't delete elements from an array, by definition they're of fixed size. What you can do is create a new array, copy all the elements from the old array except the ones that you intend to delete and return the new array. Or, use an ArrayList, which has operations that allow removing elements:
public E remove(int index)
public boolean remove(Object o)
public boolean removeAll(Collection<?> c)
protected void removeRange(int fromIndex, int toIndex)
First, iterate through your array and figure out how many of your target element are present.
Once you know that, you know the size of your new array. As Oscar mentions, you can't "remove" from an array, you just make a new array without the elements you don't want in it.
int targetCount = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == target) {
targetCount++;
}
}
Now you know how many items will be in your new array: array.length-targetCount.
int[] newArray = new int[array.length-targetCount];
int newArrayIdx = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] != target) {
newArray[newArrayIdx] = target;
newArrayIdx++;
}
}
Here we iterate through the old array and check each element to see if it's our target. If it's not, we add it to the new array. We have to keep track of our old array's index and our new array's index independently or we may risk trying to assign an index outside of the array bounds.
This is a common interview question. In the solution presented by Oscar you do not know what will be the size of the new array. So the solution does not work or is memory inefficient.
Trick is to loop over the array and at any time when you encounter an element equal to the given element you put that element towards the end of the array and swap it with the element that was there at the end position. By doing this you are collecting all occurrences of given element at the end of the array.
Here is a working logic
deleteElement(int[] given, int elem) {
int endIdx = array.length - 1;
for(int idx = 0; idx <= endIdx; idx++) {
if(given[idx] == elem) {
//swap idx with endIdx
int tmp = given[endIdx];
given[endIdx] = given[idx];
given[idx] = tmp;
endIdx--;
}
}
return Arrays.copyOfRange(given, 0, endIdx);
}

Categories

Resources