Cannot understand Array bounds [duplicate] - java

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 4 years ago.
I've been learning to code recently, but unfortunately iterating through arrays and understanding their Length property and not going out of bounds eludes me.
I have the following exercise that I need to solve in Java - input a few numbers, parse them and put them into an array then get the three largest numbers in it and print them in descending order. I managed to do it, but I did need to look up the last part, as I was getting ArrayIndexOutOfBoundsException. I have hardcoded the values in the Array, in order to try and understand it, but I'd appreciate some help on the matter.
Here is my solution:
int[] numbers = {1, 2, 3, 4, 5, 6};
Arrays.sort(numbers);
int count = Math.min(3, numbers.length);
for (int i = 0; i < count; i++) {
System.out.println(numbers[i + numbers.length - 1]);
What I am trying to do here is print them in ascending order, as printing them in descending will be numbers[numbers.length - 1 - i]. On my example I am getting OutOfBounds. If I do i + numbers.length - 3 it works.
Will someone be so kind as to explain why? I know it's a stupid question but I just can't seem to understand it.

Image that the array is like a chain of objects. You can always access any of those objects if you know its index. So in the case you have an array of length 9 that contains the first 9 positive integer you will have valid indexes through 0 to 8.
0 1 2 3 4 5 6 7 8
[1][2][3][4][5][6][7][8][9]
to print out the the values inside the array you could use:
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]);
}
and if you would like to backward print it then you should start from it's last index and decrement the i until it greater or equal to the starting index of the array:
for (int i = values.length - 1; i >= 0; i--) {
System.out.println(values[i]);
}
Whenever you try to access an index that is out of the bound of valid indexes it will result to IndexOutofboundsException. So if you like to invoke any arithmetics with calculating the indexes be aware of the fact that you have only few valid values for it.

So in this context let's look at it in terms of the minimum and maximum values that the array access can have
So for the minimum value of i (0), we get i + numbers.length - 1 = 0 + 6 - 1 = 5
and for the maximum of i we either get 3 or numbers.length:
In the case of 3: i + numbers.length - 1 = 3 + 6 - 1 = 8
In the case of numbers.length we get i + numbers.length - 1 = 6 + 6 - 1 = 12
You need to make sure that the possible values that the array will iterate between is always going to give a value within the bounds of the array (as clearly this does not)

Tried to run
for (int i = 0; i < count; i++) {
System.out.println(i + numbers.length - 1);
}
It prints:
5
6
7
Your array has 6 items and is indexed from 0 to 5. When you try to get item that has index >=6 it throws ArrayIndexOutOfBoundsException

If you want to print them in descending order use
System.out.println(numbers[numbers.length - 1 - i])

Related

What is wrong with my code/ what can I do to solve this assignment?

In this lab, you will be creating a program that merges two arrays of positive (greater than 0) integers. Your program will accept each array as input from the keyboard. You do not know ahead of time how many values will be entered, but you can assume each array will have a maximum length of 10,000 elements. To stop entering values enter zero or a negative number. You should disregard any non-positive numbers input and not store these in the array.
The elements of the two input arrays should be in increasing order. In other words, each array element must have a value that is greater than or equal to the previous element value. An array may contain repeated elements.
After the two arrays have been input, your program must check to make sure the elements of each array have been entered in order. If an out of order element is found, print the message “ERROR: Array not in correct order”.
Your task is to merge the two input arrays into a new array, with all elements in order, lowest to highest. Print out each of the original arrays entered, followed by the merged array.
Please note that your program must output the arrays with exactly one space between each of the numbers.
Sample Run 1:
Enter the values for the first array, up to 10000 values, enter zero or a negative number to quit
3
3
5
6
8
9
-1
Enter the values for the second array, up to 10000 values, enter zero or a negative number to quit
3
4
5
6
-5
First Array:
3 3 5 6 8 9
Second Array:
3 4 5 6
Merged Array:
3 3 3 4 5 5 6 6 8 9
My code was:
import java.util.Scanner;
class Main{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int one1=0;
int two1=0;
int a = 0;
int b = 0;
int flag = 0;
int[]one=new int[10000];
int[]two=new int[10000];
System.out.println("Enter the values for the first array, up to 10000 values, enter a negative number to quit");
while (a==0){
int first = scan.nextInt();
if (first<=0) a++;
else{
one[one1]=first;
one1++;
}
}
System.out.println("Enter the values for the second array, up to 10000 values, enter a negative number to quit");
while (b==0){
int second = scan.nextInt();
if (second<=0) b++;
else{
two[two1]=second;
two1++;
}
}
System.out.println("First Array:");
for (int i = 0 ; i < one1 ; i++){
System.out.print(one[i]+" ");
}
for (int i = 0 ; i < one.length-1 ; i++){
if (one[i]>one[i+1]) flag++;
}
System.out.println("Second Array:");
for (int i = 0 ; i < two1 ; i++){
System.out.print(two[i]+" ");
}
for (int i = 0 ; i < two.length-1 ; i++){
if (two[i]>two[i+1]) flag++;
}
int[]combo = new int[one.length+two.length];
for (int i = 0 ; i < combo.length-1 ; i+=2){
combo[i]=one[i];
combo[i+1]=two[i];
}
if (flag>0) System.out.println("ERROR: Array not in correct order");
else{
for (int i = 0 ; i < combo.length; i++){
System.out.print(combo[i]+" ");
}
}
}
}
This code keeps giving me runtime error- what am I doing wrong?
I am sorry, your merge algortithm is all wrong. You create an array combo of length one.length + two.length, that is, 20000 (I think one1 + two1 should suffice). Then you try to fill the new array by looping through it two elements at a time:
for (int i = 0; i < combo.length - 1; i += 2) {
So i is 0, 2, 4 etc. through 19998 (the last even number before 20000). Except when it gets 10000, you try to pick out one[i], that is one[10000], which is outside the one array. This gives the ArrayIndexOutOfBoundsException.
How I found out? The stack trace gives a line number. The line it mentions is
combo[i] = one[i];
It also mentioned the number 10000, so I knew this was the value of i at this point.
I think that what you were trying to do, was fill elements 0 from one and two into elements 0 and 1 of combo, I think it works so far. Then you wanted to fill element 1 from each array into elements 2 and 3; but since you have added 2 to i, you fill in element 2 from each source array and never use element 1 from them. Or any element from odd indices.
Before you mend that problem, allow me to mention one more thing. I think with your logic, input arrays 2 5 and 11 30 will come out as 2 11 5 30. This doesn’t fulfil “with all elements in order, lowest to highest”. So I think you should think your algorithm over.
the code exist many logic error,
as for Runtime Error Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10000 at..
the problem is here:
for (int i = 0 ; i < combo.length-1 ; i+=2){
combo[i]=one[i];
combo[i+1]=two[i];
}
the i from 0 to 19999 and the index of a,b is from 0 to 9999, and the code exist other simple logic problem. Please check it again.
Homework questions are very frowned upon, but still, Java is a relatively easy language. If your program is throwing a RuntimeException, you just have to read what the problem is.
In this case, it seems a loop iterates more times than it should, and you are accessing other memory space. Give it a few reads with the info provided by the error trace in mind.

Duplicate for-loop practice, beginner needs advice to study

Understanding the -1 in the for loop, need detailed explanation with for and if lines of code included?
int[] array = { 2, 5, 1, 2, 3, 5 };
Arrays.sort(array);
// why does this start counting from 1, and if l put 0 it goes to error, out of bounds?
for (int i = 1; i < array.length; i++) {
if (array[i] == array[i - 1]) { // - 1?
System.out.print(array[i]);
}
}
There is nothing inherently wrong with it.
It just makes the iteration to start with i=1 up to the array's length, but since indexing in arrays are zero-based you have to offset it when getting the value.
That is why is array[i-1]
If you put i=0 then you also have to change the ending condition to array.length-1, and you have to access the values by array[i] in order to avoid going out of bounds.
For questions like this, take the code one line at a time and try to follow what it is doing.
The first thing you do here is to create an array, then sort it. After the Arrays.sort(array) call, your array will contain the following:
index 0 1 2 3 4 5
----------------------
contents 1 2 2 3 5 5
Remember, arrays are zero-indexed - that means the very first element is located at index 0. (The contents of the array don't matter, it's the index you want to pay attention to.)
Arrays cannot have indexes less then zero, and they also cannot have indexes greater than their length-1. So, for your example, that means you cannot use -1 as an index because it is less than 0. You also cannot use 6 as an index, since 6 is greater than the length of the array (6) minus one.
In the initialization of the for-loop, you set i equal to 1 for the first iteration. Though unconventional, it's perfectly legal. This simply represents which index we will start from in the array. So for the first iteration of the loop, array[i] will be pointing to the value 2, and array[i-1] points to the value 1.
index 0 1 2 3 4 5
----------------------
contents 1 2 2 3 5 5
i ^
i-1 ^
Now, what if you set i to start at index 0 instead? Well, then array[i] will point to the 0th index (value 1)... but what does array[i-1] point to?
index 0 1 2 3 4 5
----------------------
contents 1 2 2 3 5 5
i ^
i-1 ^
It's pointing to index -1. Since arrays can't have indexes of -1, this is causing your IndexOutOfBoundsException. Hopefully that makes sense.

Why is my int[] array loop out of bounds?

Warning: I am very new to Java and programming in general. I'll try to be as clear as possible.
I am attempting to take a simple integer (inputnumber), convert it to a string (temp), create a new int[] array (numberarray), and loop through this int[] array, starting from the last digit, and print out the name of the digit.
I am rather sure that the conversion from integer to String to int[] array was functional due to Eclipse debugging, but am stumped as to why I am getting an ArrayOutOfBounds message from Eclipse for such a simple for loop. Any clues as to what I am doing wrong is appreciated.
String temp = inputnumber.toString();
int[] numberarray = new int[temp.length()];
for (int i=0;i<temp.length();i++) {
numberarray[i] = temp.charAt(i);
}
for (int i=temp.length();i>0;i--) {
if (numberarray[i]==1) System.out.print("one.");
if (numberarray[i]==2) System.out.print("two.");
if (numberarray[i]==3) System.out.print("three.");
if (numberarray[i]==4) System.out.print("four.");
if (numberarray[i]==5) System.out.print("five.");
if (numberarray[i]==6) System.out.print("six.");
if (numberarray[i]==7) System.out.print("seven.");
if (numberarray[i]==8) System.out.print("eight.");
if (numberarray[i]==9) System.out.print("nine.");
if (numberarray[i]==0) System.out.print("zero");
}
The Eclipse error message I am getting is:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at jt.Intermediate8.main(Intermediate8.java:44)
Arrays are 0-indexed in Java. This means the last value is at index NUMBER_OF_ELEMENTS - 1
Therefore, in your for loop, you should change
int i=temp.length() // this is last index + 1 (since we are starting from 0)
To:
int i=temp.length() - 1 // this is last index
Also, as #brso05 said, don't forget to change your loop-ending condition to i>=0 since the last value going backwards will be at index 0.
Your for loop:
for (int i = temp.length(); i >= 0; i--)
You're starting the loop at temp.length(). That's not a valid index. Perhaps you want temp.length()-1?
You should be doing temp.length() - 1. The reason is that the array starts with index 0 not 1 so the last element in an array is stored at the length - 1. If there are 10 elements then 0-9 are your indexes. Also change i>0 to i>=0 if you want to hit all elements.
for (int i=(temp.length() - 1);i>=0;i--) {

Counting Int Occurrences in an Array

I am trying to count the occurrences of integers in an array. I was able to get it to work by piecing together some code I found online but I don't really understand why its working. What I have is:
int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[hand.length];
for (int i = 0; i < hand.length; i++)
numOccurence[hand[i]]++;
for (int i = 1; i < numOccurence.length; i++)
if (numOccurence[i] > 0)
System.out.println("The number " + i + " occurs " + numOccurence[i] + " times.");
The output is:
The number 2 occurs 2 times.
The number 3 occurs 1 times.
The number 4 occurs 2 times.
How is this code counting the number of occurrences properly? I don't see how its accomplishing this. Thank you in advance!
This is only working because you've a good luck. Try making the second element in the hand array as 5 and see what happens. Its because the number present at the current index of hand is taken as the index of array numOccurence. In case of a number greater than or equal to the length of the numOccurence, you'll get the ArrayIndexOutOfBoundsException.
Thereforce, you can better use a Map for this where the key would be the number and the value could be its count.
Something like this:-
Map<Integer, Integer> numOccurence = new HashMap<Integer, Integer>();
for (int i = 0; i < hand.length; i++) {
int cnt = 1;
if (numOccurence.containsKey(hand[i])) {
cnt = numOccurence.get(hand[i]);
cnt++;
}
numOccurence.put(hand[i], cnt);
}
This code does not really work. At least it does for the author's use case but probably not for yours.
Try with {2, 4, 99, 2, 4}; as hand and it will fail.
The author takes the number found in hand as the index of array numOccurence.
numOccurence has the following structure : {nb occ of 0; nb occs of 1;...; nb occs of 4}. Here 99 will be out of bounds.
When you create an array
int[] numOccurence = new int[hand.length];
it is populated by their default values. For primitive int this value is 0.
This will of course only work if hand contains numbers less than or equal to max index (length -1) of the array otherwise it's ArrayIndexOutOfBound for you mister!
Actually it's the same method for creating histogram for picture ;)
You create a table where you will gather the occurrence.
numOccurence[0] will stock the number of 0
numOccurence[1] will stock the number of 1
etc.
That's what is done by this
for (int i = 0; i < hand.length; i++)
numOccurence[hand[i]]++;
it adds 1 to the value in the case corresponding to the number hand[i]
so if you look at this step by step
first he will take hand[0] = 2
so he will put
numOccurence[2] = numOccurence[2] + 1 ;
which is same (but faster to write) as
numOccurence[2]++;
This kind of performing a count is called counting sort.
The advantage of counting sort is it's speed. The disadvantage is the memory requirements when sorting big numbers.
There is a bug in the code:
int[] numOccurence = new int[hand.length];
numOccurence needs to be as long as the highest number in the list (not the number of numbers in the list). Try changing one of the numbers to 15 and you will get an exception.
The code iterates through the given array hand. it takes each value encountered as an index into the array numOccurrence. for each number n in hand, this will happen exactly as often as n occurs in hand, and each time this happens, the nth element of numOccurrence will be incremented.
thus numOccurrence is effectively an array of counters (assuming that the array elements are initialized with 0).
drawbacks of this approach:
the number of counters allocated depends on the magnitude of numbers in your handarray.
if the numbers in your hand array are distributed sparsely, most of the allocated space is never used.
alternative
you could improve the code by sorting hands first. in the sorted array the indexes of all occurrences of a given number are contiguous, so you scan the sorted array once needing a single counter only to compile the frequencies.
First of all the code is wrong. You should set the size of numOccurence array to the max number value from hand array + 1. For example:
int[] hand = {2, 100};
int[] numOccurence[] = new int[101];
(you should obviously find max number programatically)
Now let's take a look at the algorithm.
It takes each number from hand array, treats it as a numOccurence index value and increments number at that index by 1 in hand array. Note that all elements of numOccurence array are 0 by default at the beginning.
int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[5];
Steps:
i = 0 (nothing happens, because there is no 0 in hand array)
i = 1 (same situation as for 0)
i = 2 (there are two 2 numbers in hand array, so we do operation numOccurence[2] += 1 twice, which in result gives 0 + 1 + 1 = 2. So we got numOccurence[2] = 2)
it continues for all numbers from 0 to max number from hand array (here: 100).

Java - for() loop and arrays

The next question is from test that I've done.. I've run the code on BlueJ and don't get why the return value is 5...
public int mystery(int[] myStuff, int num) {
for (int k = myStuff.length - 1; k >= 0; k--) {
if (myStuff[k] < num) {
return k;
}
}
return -1;
}
myStuff = 2, 4, 0, 1, -6, 3, 8, 7, 5
num = 4
In the test I wrote - 0. Why 5? I don't get it!
What is the part of the
`return -1`
?
You're getting 5 because that is the index of the first element in the array whose value is less than 4 (when starting from the last element and working towards the first). Note that you have:
return k;
...where k is your array index. If you wanted to get the value at that index, you should do:
return myStuff[k];
Here's a simple example that shows that your result is in fact correct: http://ideone.com/7byIY
And the return -1; is just saying "if no elements are less than the specified number then return a value of -1 to indicate that no match was found". This is not an uncommon practice (returning an intentionally chosen, invalid value to indicate that there is no result).
It returns five because that's the index of 3 in your input array, which is the first number strictly smaller than 4 starting from the end of your array.
return -1; would be executed if none of the items in your array satisfy the "strictly smaller than num" criteria.
The function returns the largest index in the array corresponding to a value less than the target. This is accomplished on arbitrary arrays by scanning from the back and returning the first index corresponding to a value less than the target. In your example, 3 < 4 at index 5, so this is the correct answer. If no values smaller than the target are found, -1 is used as a sentinel value to indicate the algorithm failed to find a valid answer.
That function gives the position of the last number in the first argument that's smaller than the second argument (or -1 if all the numbers are larger than the second argument; -1 is a special value with no chance of ambiguity because there's no position -1).
That number is 3 and its position is 5 (starting with 0).
This function just searches for the last value in the array which is greater or equal than num. Let's compute the check myStuff[k] < 4 for all values:
0 1 2 3 4 5 6 7 8 // k
2 4 0 1 -6 3 8 7 5 // myStuff[k]
true false true true true true false false false // myStuff[k] < 4
The last index for which myStuff[k] < 4 is true is obviously 5, so that's the correct answer.
return -1 is needed so that the function returns a value, even if all elements of myStuff are larger than num. For example, with num = -99, the result would be -1.
your return-1 doesn't mean anything for the parameters you have passed here.
as the condition is true for value 3 so it returns the value of k, which is nothing but 5 bt that movement. this is because you are iterating backwards.
mystery(myStuff=[2,4,0,1,-6,3,8,7,5], 4)
then the for begins
for (int k = 8; k>=0; k--)
if ( myStuff[8]=5 < 4) - NO
2nd iteration
k = 7 if (7 < 4) - NO
... so on
k = 6 if (8 < 4) - NO
k = 5 if (3 < 4) - YES - so return k = 5
The last part means:
if myStuff does not have any value < num then it returns -1

Categories