updating the array dynamically [duplicate] - java

This question already has answers here:
How do I remove objects from an array in Java?
(20 answers)
Closed 8 years ago.
I am beginner to java coding, I am facing some complexity in updating the array.
My problem is I have an array named s1[] which consists of 10 elements from that I have to choose 1st 3 elements and I have to store in one array i.e. max1[] array and in next array I have to choose randomly 3 elements from the same array i.e. s1[] and store it in max6[] and I need to do comparison between the two arrays i.e. max1[] and max6[] so that the matching values will be stored.
My code looks like this (here f1 = 3)
for (i1 = 0; i1 < f1; i1++) {
max1[i1] = s1[i1];
System.out.println("1st tree random leaf nodes of phy m/c 1 at tree 1 : " + max1[i1]);
System.out.println(" \n ");
max6[i1] = s1[(int) (Math.random() * f1)];
System.out.println(" random leaf nodes of phy m/c 1 at tree 2: " + max6[i1]);
System.out.println(" \n ");
}
for (int l1 = 0; l1 < f1; l1++) {
for (int k1 = 0; k1 < f1; k1++) {
if (max1[l1] == max6[k1]) {
c1[l1] = max1[l1];
k1++;
System.out.println("the value after crossover is:--------->" + c1[l1]);
break;
}
}
}
now what I want is that I have to repeat the loop for some iterations so that in the next iteration the values of the max1 array in 1st iteration shouldn't be repeated means I have to permanently remove the elements from s1 array until s1 array contains zero elements in it

I have two suggestions for you, it's up to you which you prefer.
Firstly I would suggest converting the array to a list and removing the necessary elements from the list then converting back to the array. Code follows :
List<Double> list = new ArrayList<Double>(Arrays.asList(s1));
list.remove(i1);
s1 = list.toArray(new Double[0]);
Secondly you can shift the specific element of the array to the back and just iterate one position less than the length. This will require you adding an extra int variable to either record the number of elements in the array or to record the amount of deleted elements, the former being the better idea. Code follows :
double temp;
for(int i = 0; i < test.length - 1; i++){
temp = s1[i];
s1[i] = s1[i + 1];
s1[i + 1] = temp;
}
nrE = nrE - 1;
This will require you to have an int nrE with value of the length of the array(here 10) before your first for loop.
Both of these should be implemented inside the for loop at the end of the iteration.
From what I've seen my first suggestion is used most.
Note : I may misunderstand what you are trying to achieve, but I believe your code for getting the 3 random elements is faulty. If f1=3 and you take element at the position Math.random() * f1 you will always get an element in the range 0 to 3. To fix this you can instead use Math.random() * s1.length

Related

How to reverse slice of array java

I've been attempting to reverse a slice of a list in java.
The equivalent in python (though perhaps not the best way - I don't care about this, just want to get my point across) would be:
myList = [0,1,2,3,4,5,6,7,8,9,10]
reverseSlice = myList[2:6]
reverseSlice.reverse()
myList[2:6] = reverseSlice
When I tried to manually implement this in Java, I tried this:
public static int[] reverse(int[] x,int a1, int a2) {
a1--;
int[] rArr = new int[a2-a1+1];
for (int ind = a1; ind<a2; ind++) {
rArr[a2-ind-1] = x[ind];
}
for (int ind = a1; ind<a2; ind++) {
x[ind] = rArr[ind];
}
return x;
}
However, when I run this:
int[] cows1 = new int[]{0,1,2,3,4,5,6,7,8,9,10};
cows1 = reverse(cows1,2,6);
for (int i : cows1) {
System.out.print(i + " ");
}
I get 0 4 3 2 1 0 6 7 8 9 10 .
I'm really confused how I got this, as in my function, I don't introduce new values, so the "0" shouldn't have appeared.
My Question: Why is my code returning values that are not in the list?
The 0 value which is coming might be because of accessing an uninitialized value from rArr array. For the purpose of reversing, an extra array is not required. You can simply swap the values from the starting index to the end index. I have tested the following code and it gives correct output
public class Solution2 {
public static void main(String args[])
{
int[] cows1 = new int[]{0,1,2,3,4,5,6,7,8,9,10};
cows1 = reverse(cows1,2,6);
// both indices are inclusive
for (int i : cows1) {
System.out.print(i + " ");
}
}
public static int[] reverse(int[] x,int a1, int a2) {
for (int i = 0; i < (a2-a1+1)/2; i++) {
swap(x,a1+i,a2-i);
}
return x;
}
private static void swap(int[] x, int i, int j) {
// System.out.println("values swappeed are "+ x[i] + " " + x[j]);
int temp = x[i];
x[i] = x[j];
x[j] = temp;
}
}
and the output comes as
0 1 6 5 4 3 2 7 8 9 10
The problem seems to be the first line of your reverse function: a1--; not preserving the original value for your start index.
The method call
The purpose of the reverse function is to reverse only the portion of the array bound by variable values a1 and a2. On a side note, never use meaningless names like that. Better names for these variables could've been startIndex and endIndex or similar naming (a1 and a2 don't really mean anything).
For values (2, 6), the reverse function should extract the portion of the array starting at index 2 and ending on index 6. I am assuming the end index is not inclusive, so it should only grab values at index 2, 3, 4, and 5. However, the first thing the method does is decrement the start index, so it actually starts at index 1.
From there, the function successfully reverse the values located at these indices [4,3,2,1]. The question is now, what happens to the value at index 5? Let's see what this part of the code does new int[a2-a1+1]. The value of a2 is 6 and the new value of a1 is 1 because it was decremented in the first line. That means that your new array is of size [6-1+1] which is 6. That seems to be incorrect. Only 4 values are required to be reversed and the array is one element too big. The last index of this array is defaulted to integer value of 0.
The swap
First loop:
for (int ind = a1; ind<a2; ind++) { // starts with a1 = 1 and a2 = 6
rArr[a2-ind-1] = x[ind]; // rArr[4] = x[1]: first iteration is off by 1
}
Second loop:
for (int ind = a1; ind<a2; ind++) { // a1 = 1, a2 = 6 (starts at 1 and ends at 5 (rArr doesn't have an index 5)
x[ind] = rArr[ind]; // first iteration: x[1] = rArr[1], last iteration x[5] = rArr[5] -> this last index is accessible because array was too big and was initialized to a primitive `int` default value (0).
}
The solution
Make sure your start and end indices are preserved.
Allocate the temp array (if needed) using the original start and end indices for your calculation.
Inside the reverse() method, your first line should've been:
int[] rArr = new int[a2-a1]; // allocates an array of size 4 (6-2)
From here, if the rest of the method is wrong, you will not see a zero anywhere in the reversed array. At worst, you would've seen an offset problem if your start index was erroneously calculated. And that, I think, would've been easy to spot and fix.
If you are new at programming, and even if you are more of an "expert", you should always work out these problems on paper (or on a board) before you attempt to code and walk through your logic. You will be amazed as to how many logic errors you will catch before you code.

Need help understanding the structure of this insertion method

I am working on a homework assignment involving array sorting methods, we are given the methods, and I'm having a little trouble understanding how this insertion sort method functions. More specifically, the role the two variables passed to the method play.
As I understand, the Key variable describes the index of the array that you'd like to place your inserted number in and the item is the number itself. Within main, I simply request the user to enter two numbers and pass them to the method, one for the key and the other for the item. Here is the given code for this segment:
public final void insertion(double Key, double Item)
{
if (arraySize == 0)
{
arr[0] = Item;
}
/* find the position for inserting the given item */
int position = 0;
while (position < arraySize & Key > arr[position])
{
position++;
}
for (int i = arraySize; i > position; i--)
{
arr[i] = arr[i - 1];
}
arr[position] = Item;
arraySize = arraySize + 1;
}
However, when I pass doubles to the method as I have explained, I get an error stating that index (array length) is out of bounds for length (array length).
Clearly, I am misunderstanding the purpose or structure of this method and I can't figure it out. Any help would be appreciated. I know this is a very simple problem.
EDIT: Here is how I initialize my array, the given code is in a separate class from my main method:
public static double[] arr;
private int arraySize;
public sortedArrayAccess(int scale)
{
arr = new double[scale];
arraySize = arr.length;
}
Within my main method:
System.out.print("Enter an array size: ");
int d = sc.nextInt();
sortedArrayAccess test = new sortedArrayAccess(d);
for(int i=0;i<test.arr.length;i++)
{
System.out.print("Enter a number for index " + i + ": ");
double c = sc.nextDouble();
test.arr[i] = c;
}
How do you initialize ‘arr’ variable?
Anyway the problem is that when you create the array - you should specify initial capacity. And every time when you add the element into array you are about to increase it.
When you try to ask for for a cell of array indexed i if array capacity is less then I - you’ll be given the arrayOutOfBoundsException.
Your problem is here:
if (arraySize == 0)
{
arr[0] = Item;
}
You are assigning the Item to the first element in the array. But the array size must be empty as stated by the if (arraySize == 0)
So you have two options:
adjust the size of the array (by creating a new one)
or return an error
if (arraySize == 0)
{
arr[0] = Item;
}
As you know, in computer science, indices starts from 0. Which means arr[0] here is the first slot of your array. if arraySize is 0, there is no such index arr[0]. Your code tries to insert the Item to zero sized array. This causes Index out of bound exception.
By the way, If it is a sorting algorithm for the values, "Key" variable is not required. You can delete it. But if it is required, you should sort the elements by their key values.
For example if we have:
element 1 -> key= 101 , value= 6
element 2 -> key= 201 , value= 9
element 3 -> key= 301 , value= 2
you should not sort them as element 3 < element 1 < element 2
you should sort them like: element 1 < element 2 < element 3 in order to their key values.
In other words, if you want to sort them by their values, passing key values as a parameter is meaningless.

Java how to take second element of array

I'm working on an assignment that requires the user to input an undecided number of integers, and then those numbers are to be used in other calculations. But for example if I have these 6 numbers. 1 2 3 4 5 6 and I want to extract only 2 4 and 6 from the input how would I do that? (make notices that this is just an example, the user can put in 20 different numbers, or only 4) I just want to be able to chose to pick every second element. To add more info, I need the first number in the array to be for one calculation, then the second for another calculation and then the first and the second. Basically I want to be able to assign every even array index numbers to a integer and every odd array index numbers to another integer. Like this :
"if (i % 2 == 0){int first = numbers [i];
System.out.println("This is the first" + first) }
else if (i % 2 == 1) { int second = numbers [i] ; System.out.print("This is the second. " + second);}"
But when I do so, it only appears in the first one..
you need to collect all of elements that index is odd in an array due to array index start at 0.
// all of the second elements in numbers are collected into partial array
int[] partial = new int[numbers.length >> 1];
// the initial value of i=1 means iterate the first second element at first
// i+=2 means iterate the next second element in array
for(int i=1;i<numbers.length;i+=2){
partial[(i-1)>>1] = numbers[i];
}
If you are familiar with Java 8 streams then you could use an IntStream to generate the indices and then pick out every odd one:
int[] everySecond = IntStream.range(0, array.length)
.filter(i -> i % 2 == 1).mapToInt(i -> array[i]).toArray();
So just for clarification you want every second iteration of the array without the order of the numbers having any affect? So the array of numbers could be 4,2,6,8 and the return should be 2 and 8 in this example?
If this is the case then you can can assign the for loop to only read every second iteration.
To do this you will need the length of the array.
int arrLength = arr.length;
for (int i = 1; i < arr.length; i = i+2) {
#dosomething
}
// This is from user
int[] userInput = {};
int[] pickedNumbers = new int[userInput.length/2];
if(userInput.length > 1)
{
for (int i = 1; i < userInput.length; i = i + 2)
{
pickedNumbers[i / 2] = userInput[i];
}
}
// pickedNumber is the array you can use.

JAVA ArrayIndexoutofBoundException issue

A perfect number is one that is the sum of its factors, excluding itself. The 1st perfect number is 6 because 6 = 1 + 2 + 3. The 2nd perfect number is 28 which equals 1 + 2 + 4 + 7 + 14. The third is 496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248. In each case, the number is the sum of all its factors excluding itself.
Write a method named henry that takes two integer arguments, i and j and returns the sum of the ith and jth perfect numbers. So for example, henry (1, 3) should return 502 because 6 is the 1st perfect number and 496 is the 3rd perfect number and 6 + 496 = 502.
I have done this far:: but this is showing ArrayIndexOutOfBoundException at this line temp[index] = j; please help me to solve this OutOfBound issue, Thanks..
public static int henry (int a, int b){
List<Integer> arr = new ArrayList<Integer>();
int henryNumber = 0;
for(int i=4;;i++){
List<Integer> temp = new ArrayList<Integer>();
int sum = 0;
for(int j = 1; j<i; j++){
if(i%j == 0 ) { temp.add(j); }
}
for (Integer item : temp) { sum+=item; }
if(sum == i) arr.add(i);
if(arr.size() == b) {
henryNumber = arr.get(a-1) + arr.get(b-1);
break;
}
}
return henryNumber;
}
int[] temp = {};
This sets temp to an array of 0 elements. So when you try to access temp[index] where index is = to 0 its out of bounds because the array doesn't have even a single element
You would need to create an array of x number elements by doing:
int[] temp = new int[x];
and then you can set the value at each of the indicies to whatever value you want.
An array has a fixed length as soon as it it created, and that length cannot be changed.
int[] temp = {};
This creates an empty array. Its length is zero. You can't change that, you can't add any items to it.
temp[index] = j;
This tries to put something in the temp array. However, as I said, the array is empty, its length is zero, so any value of index would be out of bounds.
Using a List (which is commented out in your source) will allow you to create a growing collection of elements. Alternatively, you have to think of a proper size for your array, that will hold all the elements you'll be using, and use that size when you create the array.
Try doing
int[] temp=new int[i];
instead of
int[] temp={};
I have never assigned an array like this before.

Why does this merge sort give incorrect results?

My assignment is to merge two arrays using int arrays that the user fills and we have to assume that there will be a maximum of 10000 inputs from the user, and the user inputs a negative number to stop. Then sort the array from least to greatest and print it out. Initially i thought that this would be quite easy but when i finished, i began getting outputs such as:
Enter the values for the first array, up to 10000 values, enter a negative number to quit: 1
3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
1
3
5
Second Array:
2
4
6
Merged Array:
6 1 2 3 4 5
as you can see, the six is out of place and i have no idea how to fix it. Here is the source code, i have included copious comments because I really want you guys to help me out to the best of your abilities. IF it's possible to use the same exact technique without implement new techniques and methods into the code please do so. I know there are methods in java that can do all of this in one line but it's for an assignment at a more basic level.
import java.util.Scanner;
public class Merge
{
public static void main(String [] args)
{
Scanner scan = new Scanner(System.in);
int [] first = new int[10000]; //first array, assume 10k inputs max
int [] second = new int[10000]; //first array, assume 10k inputs max
boolean legal = true; //WILL IMPLIMENT LATER
int end = 0; // set how many elements to put in my "both" array
int end2 = 0;// set how many elements to put in my "both" array
System.out.print("Enter the values for the first array, up to 10000 values, enter a negative number to quit");
//get values
for(int i = 0; i<first.length; i++)
{
first[i] = scan.nextInt(); //fill first with user input
if(first[i] <0) //if negative number, stop loop
{
end = i; //get position of end of user input
break;
}
}
System.out.println("Enter the values for the second array, up to 10000 values, enter a negative number to quit");
for(int i = 0; i<second.length; i++) //exact same as the first get values loop
{
second[i] = scan.nextInt();
if(second[i] <0)
{
end2 = i;
break;
}
}
System.out.print("First Array:\n");
for(int i = 0; i<first.length; i++) //print first array
{
if(i == end) //this prevents from printing thousands of zeros, only prints values that user inputed
break;
System.out.println(first[i] + " ");
}
System.out.print("Second Array:\n");
for(int i = 0; i<second.length; i++) //same as printing first array
{
if(i == end2)
break;
System.out.println(second[i] + " ");
}
int [] both = new int[(end)+(end2)]; //instanciate an int array to hold only inputted values from first[] and second[]
int [] bothF = new int[(end)+(end2)]; //this is for my simple sorter algotithm loop
for(int i = 0; i<both.length; i++) //fill both with the first array that was filled
{
both[i] = first[i];
}
int temp = end; // see below
for(int i = 0;i<both.length; i++) //fill array with the second array that was filled(starting from the end of the first array so that the first set is not overwritten
{
if(temp<both.length){ //this prevents an out of bounds
both[temp] = second[i];
temp++;}
}
//simple sorting algorithm
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
bothF[d] = both[d];
both[d] = both[i];
both[i] = bothF[d];
}
}
}
System.out.println("Merged Array:"); //print the results
for(int i = 0; i<both.length; i++)
{
System.out.print(both[i] + " ");
}
//System.out.println("ERROR: Array not in correct order");
}
Your sorting algorithm is faulty.
It's similar to selection sort, in that you take two elements and swap them if they're out of place. However, you don't stop the comparisons when you should: when the index d is less than the index i, the comparison-and-swap based on arr[d] > arr[i] is no longer valid.
The inner loop should terminate with i=d.
The logic of your sort goes something like this:
On the d-th loop, the elements at d+1 and to the right are correctly sorted (the larger numbers). This is true at the beginning, because there are 0 elements correctly sorted to the right of the right-most element.
On each of the outer loops (with the d counter), compare the d-th largest element slot with every unsorted element, and swap if the other element is larger.
This is sufficient to sort the array, but if you begin to compare the d-th largest element slot with already-sorted elements to its right, you'll end up with a larger number in the slot than should be. Therefore, the inner loop should terminate when it reaches d.
Sure, you can do it like this
for (int i = 0; i < end; i++) {
both[i] = first[i];
}
for (int i = 0; i < end2; i++) {
both[i + end] = second[i];
}
// simple sorting algorithm
for (int d = both.length - 1; d >= 0; d--) {
for (int i = 0; i < d; i++) {
if (both[i] > both[d]) {
int t = both[d];
both[d] = both[i];
both[i] = t;
}
}
}
Output(s) -
Enter the values for the first array, up to 10000 values, enter a negative number to quit3
5
-1
Enter the values for the second array, up to 10000 values, enter a negative number to quit
2
4
6
-1
First Array:
3
5
Second Array:
2
4
6
-1
Merged Array:
2 3 4 5 6
First I will start with some recommendations:
1.Give end1 and end2 the initial value as the array lengths.
The printing part - instead of breaking the loop - loop till i == end(if its not changed by the first part it will stay the array length).
One suggestion is to use a "while" statement on the user input to do the reading part (it seems cleaner then breaking the loop- but its OK to do it like you have done too).
Try to use more functions.
now to the main thing- why not to insert the numbers from both arrays to the join array keeping them sorted?
Guiding:
Keep a marker for each array.
Iterate over the new join array If arr1[marker1]> arr2[marker2]
insert arr2[marker2] to the joint array in the current position.
and add 1 to marker2. and the opposite.
(don't forget to choose what happens if the are equal).
This can be achieved because the arrays were sorted in the first place.
Have fun practicing!
I guess you have sort of a reverse "selection sort"-algorithm going on there. I made an class that run your code and printed out the output after every swap. Here is the code which is the same as you got in your application with the addition of print.
for(int d = both.length -1;d>=0;d--)
{
for(int i = 0; i<both.length; i++)
{
if(both[d]<both[i])
{
int temp = both[d];
both[d] = both[i];
both[i] = temp;
printArray(both);
}
}
}
and when we run this on an example array we get this output
[9, 8, 7, 6]=
-> 6879
-> 6789
-> 6798
-> 6978
-> 9678
The algorithm actually had the correct answer after two swaps but then it started shuffling them into wrong order. The issue is the inner for loops end parameter. When you have run the outer loop once, you can be certain that the biggest number is in the end. 'd' is here 3 and it will swap out a bigger number every time it encounters it. the if clause comparisions in the first loop is 6-9 (swap), 9-8, 9-7, 9-9. All good so far.
Potential problems comes in the second iteration with 'd' as 2. Array is now [6,8,7,9] and comparisons are 7-6, 7-8 (swap with result [6,7,8,9]), 8-8, 8-9 (swap!!) resulting in [6,7,9,8]. the last swap was the problematic one. We knew that the biggest number was already in the last spot, but we still compare against it. with every gotrough of the whole inner loop it will always find the biggest number (and all other bigger than both[d] that is already in place) and swap it to some wrong position.
As we know that the biggest number will be last after one iteration of the outer loop, we shouldn't compare against it in the second iteration. You sort of lock the 9 in the array and only try to sort the rest, being in this case [6,8,7] where d = 3, value 7. hence, your inner loop for(int i = 0; i<both.length; i++) becomes for(int i = 0; i<=d; i++). As an added bonus, you know that in the last iteration i==d, and thus the code inside it, if(both[d]<both[i]) will never be true, and you can further enhance the loop into for(int i = 0; i<d; i++).
In your algorithm you always do four comparisons in the inner loop over four iterations of the outer loop, which means there is a total of 16 comparisons. if we use the i<d we'll just do three comparisons in the inner loop on the first iteration of the outer loop, then two, then one. This brings it to a total of six comparisons.
Sorry if too rambling, just wanted to be thorough.

Categories

Resources