This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 3 months ago.
import java.util.Scanner;
public class recursion_4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
printArray(a, 0);
sc.close();
}
static void printArray(int arr[], int i) {
if (i == arr.length) {
return;
}
printArray(arr, ++i);
System.out.println(arr[i]);
}
}
I am try to print array element using recursion.
But it give error of arrayIndex Out of bound.
Replace ++i with i+1
You are incrementing the value of local variable in function. Instead of incrementing, send next value to other function as you will use that local variable value while printing in your function.
++i increments the value - it actually changes it (and evaluates as the updated value.)
++i, i++ and the subtle distinction between them has been the cause of many and frustrating bugs. This is just my opinion, but I advise never using either one of them except as a single-line statement when you need to increment something. The brevity isn't worth the risk of bugs.
So if you enter printArray with i=arr.length-1, then you get past your i guard, increment i, make the recursive call (which returns), and then try to access `arr[arr.length - 1 + 1], which is out of bounds.
If you're just learning about recursion, you might be confused at how local variables and returns work in a method. Each time you call a method, that's a new stack frame (a section of memory) with completely different values for its local variables, and which returns independently. i is not "i in every usage of the method named printArray", it's only "i in the current application of the method printArray." Similarly when you return, you cease to run the current application of printArray, but not every application.
Sorry if that part's all stuff you know - I find it's one of those things that's completely mind boggling to people starting out, and then becomes completely obvious a week later.
Related
This question already has answers here:
Java: Error: variable might not have been initialized
(2 answers)
Closed 6 months ago.
class HelloWorld {
public static void main(String[] args) {
int sum;
for (int i = 0; i < 10; i++) {
if (i == 9) {
sum = 10;
}
}
System.out.println(sum);
}
}
why this code gives this error?
HelloWorld.java:9: error: variable sum might not have been initialized
System.out.println(sum);
We can look at the code and intuitively reason that sum will always have a value by the time it's used, because the loop will always execute and one of the iterations will satisfy the if condition.
But the compiler doesn't intuitively reason any of that. It sees a loop and a conditional block and it can't guarantee that sum will have a value by the time it's used. To the compiler, it's possible that loops may iterate 0 times or that conditions may never be true.
Basically, we can "test the code" in our heads and predict its outcome. But the compiler doesn't test the code, no matter how simple the code may be.
You can correct the problem by simply initializing the value:
int sum = 0;
The task was to write a method to return the least value of an array.
Would someone quickly look over my code?
public static int findMinimum (int [] array) {
for (int kohlrabi = 0; kohlrabi < array.length; kohlrabi++) {
for (int zwiebel= 0; zwiebel < array.length; zwiebel ++) {
if (array [zwiebel] < array [kohlrabi]) {
kohlrabi = zwiebel -1;
break;
}
int spinat = array [kohlrabi];
if (zwiebel == array.length-1) {
return spinat;
}
}
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation
problem: This method must return a result of type int
at Abgabe7.ArrayExercises.findMinimum(ArrayExercises.java:38)
It's a homework for my school and I definitely understood the logic behind it but cannot find my fault.
Thanks Max
I don't think you need to have two loops. One loop would work.
Simply loop though the array keeping a variable which is the lowest you've found.
You should declare a global variable before the loop then use only one for loop in your code as follows:
int zwiebel= 0;
for (int kohlrabi = 0; kohlrabi < array.length; kohlrabi++) {
if (kohlrabi == 0){
zwiebel = array[kohlrabi];
}
if (array[kohlrabi] < zwiebel) {
zwiebel = array[kohlrabi];
}
}
The lowest value in your array is now stored in the variable zwiebel.
The real mistake is that you are not taking the possibility of an empty array into account. One thing to learn in programming is to think of all possibilities (maybe you’ve discovered that already). An array in Java (and most other languages) can have length 0, that is, have no elements in it. When array.length is 0, your outer for loop doesn’t execute, so we get down to the bottom of the method without having returned anything and without having anything to return.
Java is dumb, but nevertheless smart enough to discover this problem for you. When your method is declared to return an int, it insists that it too can see that it will return an int in all cases. In your method it cannot, which is what the following message is trying to tell you:
This method must return a result of type int
One possible fix — and I may be showing you something that you haven’t learned in school yet — is to insert the following statement in the end of your method:
throw new IllegalArgumentException("Cannot find the minimum of an empty array");
Throwing an exception is an alternative to returning a value, so this statement will make Java happy. If you actually try to find the minimum of an empty array, your program will crash and give you the message “Cannot find the minimum of an empty array”. But finding the minimum of an array that has numbers in it should work now.
That said the others are correct: Your way of finding the minimum is overly complex. I have been staring at your code and still have not understood how it works. Such code is not good. In real life you will be writing code that others will need to read and change after you, and no one can change code they don’t understand, so your code would not be useful. More important than writing code that works correctly is writing readable code.
Edit: There are variations on how to do this in a simple way. For a school exercise using a for loop I would write:
public static int findMinimum (int [] array) {
if (array.length == 0) {
return 42; // or whichever value is desired in this case
}
int niedrichsteSoWeit = array[0];
for (int index = 1; index < array.length; index++) {
if (array[index] < niedrichsteSoWeit) {
niedrichsteSoWeit = array[index];
}
}
return niedrichsteSoWeit;
}
For production code I probably would not write a method but use the built-in functionality, for example:
IntStream.of(myIntArray)
.min()
.ifPresentOrElse(min -> {
// do something with min
}, () -> {
// do whatever you want to do when the array is empty
});
Don’t worry if you don’t understand a bit of this snippet. It’s mostly for more experienced programmers who might happen to read this answer.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am preparing for an exam next week, and I decided to look for some exam questions online for better preparation.
I came across this question and the answer is c. But I really want to know how or the step by step process to answer to answer a question like this. The part where I got stuck is trying to logically understand how a int m = mystery(n); How can a number equal a method? Whenever I get to a question like this is their anything important I should breakdown first?
private int[] myStuff;
/** Precondition : myStuff contains int values in no particular order.
/*/
public int mystery(int num)
{
for (int k = myStuff.length - 1; k >= 0; k--)
{
if (myStuff[k] < num)
{
return k;
}
}
return -1;
}
Which of the following best describes the contents of myStuff after the
following statement has been executed?
int m = mystery(n);
(a) All values in positions 0 through m are less than n.
(b) All values in positions m+1 through myStuff.length-1 are
less than n.
(c) All values in positions m+1 through myStuff.length-1 are
greater than or equal to n.
(d) The smallest value is at position m.
(e) The largest value that is smaller than n is at position m.
See this page to understand a method syntax
http://www.tutorialspoint.com/java/java_methods.htm
int m = mystery(n); means this method going to return int value and you are assigning that value to a int variable m. So your final result is m. the loop will run from the array's end position to 0. loop will break down when array's current position value is less than your parameter n. on that point it will return the loop's current position. s o now m=current loop position. If all the values of the loop is greater than n it will return -1 because if condition always fails.
Place the sample code into a Java IDE such as Eclipse, Netbeans or IntelliJ and then step through the code in the debugger in one of those environments.
Given that you are starting out I will give you the remainder of the code that you need to make this compile and run
public class MysteriousAlright {
private int[] myStuff;
public int mystery(int num)
{
for (int k = myStuff.length - 1; k >= 0; k--) {
if (myStuff[k] < num) {
return k;
}
}
return -1;
}
public static void main(String[] args) {
MysteriousAlright ma = new MysteriousAlright();
ma.setMyStuff(new int[] {4,5,6,7});
int m = ma.mystery(5);
System.out.println("I called ma.mystery(5) and now m is set to " + m);
m = ma.mystery(3);
System.out.println("I called ma.mystery(3) and now m is set to " + m);
m = ma.mystery(12);
System.out.println("I called ma.mystery(12) and now m is set to " + m);
}
public void setMyStuff(int[] myStuff) {
this.myStuff = myStuff;
}
}
You then need to learn how to use the debugger and/or write simple Unit Tests.
Stepping through the code a line at a time and watching the values of the variables change will help you in this learning context.
Here are two strategies that you can use to breakdown nonsense code like that which you have sadly encountered in this "educational" context.
Black Box examination Strategy
Temporarily ignore the logic in the mystery function, we treat the function as a black box that we cannot see into.
Look at what data gets passed in, what data is returned.
So for the member function called mystery we have
What goes in? : int num
What gets returned : an int, so a whole number.
There are two places where data is returned.
Sometimes it returns k
Sometimes it returns -1
Now we move on.
White Box examination Strategy
As the code is poorly written, a black box examination is insufficient to interpret its purpose.
A white box reading takes examines the member function's internal logic (In this case, pretty much the for loop)
The for loop visits every element in the array called myStuff, starting at the end of the array
k is the number that tracks the position of the visited element of the array. (Note we count down from the end of the array to 0)
If the number stored at the visited element is less than num (which is passed in) then return the position of that element..
If none of elements of the array are less than num then return -1
So mystery reports on the first position of the element in the array (starting from the end of the array) where num is bigger than that element.
do you understand what a method is ?
this is pretty basic, the method mystery receives an int as a parameter and returns an int when you call it.
meaning, the variable m will be assigned the value that returns from the method mystery after you call it with n which is an int of some value.
"The part where I got stuck is trying to logically understand how a int m = mystery(n); How can a number equal a method?"
A method may or may not return a value. One that doesn't return a value has a return type of void. A method can return a primitive value (like in your case int) or an object of any class. The name of the return type can be any of the eight primitive types defined in Java, the name of any class, or an interface.
If a method doesn't return a value, you can't assign the result of that method to a variable.
If a method returns a value, the calling method may or may not bother to store the returned value from a method in a variable.
I am trying to learn recursion in Java and have an array that takes in continuous input until the Scanner reads in a 0.
From there I have a method that (attempts) to calculate the number of positive integers in the array using recursion. This is the first recursive function I have ever written and I keep getting a stackoverflow error.
I have read tutorials and I still can't wrap my head around the basic understanding of recursion.
public class reuncF {
private static int start = 0;
private static int end = 98;
public static void main(String[] args) {
input = input.nextDouble();
list[i] = numInput;
computeSumPositive(numList, count);
}
}
return positives += solve(numbers, count++);
}
}
You forgot to stop your recursion!
There has to be some case where computeSumPositive returns without calling itself again. Otherwise it'll just keep going forever, never getting back to you.
If you did it with a loop, the loop would look like this:
int positives = 0;
for (int i = 0; i < numList.length; ++i) {
if (numList[i] > 0) {
positives++;
}
}
To do that recursively, you just find out what are the variables used in the loop. They are i, numList and positives.
computeSumPositive(int i, double[] numList, int positives)
Then we take a look at what the loop does. First, it checks whether we went too far,
so our recursive function should do that too. It'll have to return instead of just falling through like the loop does. And obviously, it must return the result:
{
if (! (i < numList.length))
return positives;
The loop then does the test and maybe increments positives, so the recursive function should also do that:
if (numList[i] > 0) {
positives++;
}
At the end of the loop, i is updated:
i++;
The loop just starts over, but the recursive function will have to call itself. Of course, we want it to use the new value of i and positives, but fortunately we updated those, so now we can just do:
return computeSumPositives (i, numList, positives);
}
The tricky bit is that the values i, numList, and are local to each call. Each invocation of computeSumPositives can see only the arguments it were given. If it changes them, none of the other invocation can see that change.
EDIT: So if we, for reasons we can only speculate about, wanted desperately for computeSumPositive to take only 2 parameters, we would have to "split up" positives across each invocation. Each invocation knows whether or not its number was positive or not; all we have to do is add them. Then it looks like this:
computeSumPositive(int i, double[] numList)
{
if (! (i < numList.length))
return 0; // I didn't find any at index i
if (numList[i] > 0) {
// Theres one I found + however many my later
// invocations will find.
return 1 + computeSumPositive (i+1, numList);
} else {
// I didn't find any, but my later invocations might.
return computeSumPositive (i+1, numList);
}
}
I find it helpful, when dealing with recursion, to figure out the termination case first.
It looks like you are treating 'count' as an index. So you could check if your at the last index in the array, if so and if the value is positive return a 1, if the value is non-positive return a 0 - dont recurse anymore.
If your not at the last index, and the value is positive return a 1 + the recursive function call, or if the value is non-positive just continue to recurse.
This will still cause a stack overflow for large arrays.
The value of count++ is the same as the value of count; the program uses the value and then increments it. But the result is that computeSumPositive keeps calling itself with the same value of count, which leads to infinite recursion. Note that each time computeSumPositive calls another computeSumPositive, each call has its own copy of the parameters (like count) and the local variables; so incrementing one computeSumPositive's copy of count has no effect on the value of count used by other recursive calls.
Change count++ to count + 1, and also add a way to halt the recursion. (At some point, you will be calling computeSumPositive to look at zero integers, and at that point, it should just return 0 and not call itself. You need to think about: how do you test whether you've reached that point?)
can anybody explain this why its happening
int i=0;
i=i++;
i=i++;
i=i++;
System.out.println(i);
it prints zero.
i++ is a postincrement (JLS 15.14.2). It increments i, but the result of the expression is the value of i before the increment. Assigning this value back to i in effect keeps the value of i unchanged.
Break it down like this:
int i = 0;
int j = i++;
It's easy to see why j == 0 in this case. Now, instead of j, we substitute the left hand side with i. The right hand side value is still 0, and that's why you get i == 0 in your snippet.
You meant to do this:
int i = 0;
i++;
i++;
i++;
System.out.println(i);
i++ actually does an assignment so if you add an = you just confuse things. These other fine responders can give you the nitty gritty, some details of it escape me. :)
First thing is you should not write this kind of code....
But if we consider for the questions sake then this simple: It has to do with the way the postfix operator "returns" the value. A postfix has precedence over the assignment operator, but the postfix operator after incrementing the value of i returns previous value of i. So i get again assigned to its previous value.
And once again don't use this construct in your code as the next programmer who sees this will come after you (with something big in his hands) :)
Let I=++, an increase, and A=i, an assignment. They are non-commutative: IA != AI.
Summary
IA = "first increase then assignment"
AI="first assignment then increase"
Counter-Example
$ javac Increment.java
$ java Increment
3
$ cat Increment.java
import java.util.*;
import java.io.*;
public class Increment {
public static void main(String[] args) {
int i=0;
i=++i;
i=++i;
i=++i;
System.out.println(i);
}
}
Related
Initialization, assignment and declaration