How does the ternary operator work in this recursive code? - java

In the last call on the stack, num will equal 0, so why doesn't the code return 0?
public static int Add(int num) {
return(num == 0 ? 0 : num + Add(num - 1));
}
int num = 7;

I believe your confusion lies in the fact that the last return statement does not directly return 0 to the main(). Instead the return statement will return to the caller of the function. In this case the caller will be itself. Here's a visualization with the extremely simple case of passing 1 to Add():
//num == 1
//Since num != 0, we will return num + Add(num - 1)
//But the compiler doesn't know what Arr(num -1) is
return num + ______;
In the blank space is where the result of Add(num -1) will go. The current call to Add() is pushed onto the stack and a new call to Add(num -1) is called:
public static int Add(int num) {
return(num == 0 ? 0 : num + Add(num - 1));
}
Here num == 0 so the method returns 0. But not to the main. It returns it to the previous call to Add(), right where the theoretical blank is. So:
return num + ______;
Becomes
return num + 0;
Since this is the last call on the stack, this returns to the main, with a result of 1, which is correct for the simply case of calling Add(1)

Related

How to fix a stack overflow in my java program?

So, I am studying java, and as a first exercise I decided to write two small and composable functions, namely a fibbonacci and a factorial function, which have a common implementation detail, however I received a stack overflow exception when I tried to separate their common part into a separate function. Any tips on what am I doing wrong?
public class BaseFunctions{
static Integer factorial(Integer num) {
return factorial(comComponent(num)-1)*num;
}
static Integer fibbonacci(Integer num) {
return fibbonacci(comComponent(num)-1) + fibbonacci(comComponent(num)-2);
}
static Integer comComponent(Integer num) {
if(num == 1 || num == 0) {
return 1;
}else if(num < 0){
throw new ArithmeticException("Num must be > 0");
}else return num;
}
}
When you reach num = 0, comComponent will return 1, calling your function with num = 0 again, thus getting stuck in an infinite loop.
A recursive function must have an exit point (which must be checked first before any recursive call), if not this leads to Stack Overflow.
What you do is leave the function without that exit point, be delegating (or so you think) this functionality to comComponent().
But take a look at the code inside factorial():
return factorial(comComponent(num)-1)*num;
Why should it ever stop? There is no return statement without a recursive call.
So your logic is wrong.
Drop comComponent() and stick to the traditional way:
static Integer factorial(Integer num) {
if (num == 1 || num == 0)
return 1;
else if (num < 0)
throw new ArithmeticException("Num must be > 0");
else
return factorial(num - 1) * num;
}
static Integer fibbonacci(Integer num) {
if (num == 1 || num == 0)
return 1;
else if (num < 0)
throw new ArithmeticException("Num must be > 0");
else
return fibbonacci(num - 1) + fibbonacci(num - 2);
}
As you can see both functions have an exit point:
if (num == 1 || num == 0)
return 1;

Resolving Stacks with Return Statements

Although I think I have a solid understanding of resolving stacks in void methods, return methods really mess up my understanding of stacks. The following method particularly confuses me as I would have thought that it would return 0, but returns 12 instead.
public static int mystery(int n) { // where the method call is mystery(7)
n--; // since n is decremented before the first
// recursive method, the first stack is method(6)
if(n > 0) // base case
mystery(n);
return n * 2; // 0 * 2 = 0?
}
My question is why does the method output 12 when mystery(7), if 0 is the last value to go into the stack. Wouldn't this method still follow LIFO?
This has to be like this:
public static int mystery(int n) { // where the method call is mystery(7)
n--; // since n is decremented before the first
// recursive method, the first stack is method(6)
if(n > 0) // base case
n = mystery(n);
return n * 2; // 0 * 2 = 0?
}
Now it will return 0 always.
From the inside out:
The innermost call to mystery (n is 1 on entry) returns 0 to its caller. The return value is not used.
The next level of mystery (n is 2 on entry) returns 2 to its caller. The return value is not used.
...and so on...
The next-to-outermost level of mystery (n is 6 on entry) returns 10 to its caller. The return value is not used.
The outermost level of mystery (n is 7 on entry) returns 12 to its caller, which is the final return value.
Let's not consider 7. Let's say your value is 3. mystery(3). In this case, the function will run 3 times.
First run:
n = 3;
n--; // n = 2
(n > 0) so mystery(2)
Second run:
n = 2;
n--; // n = 1
(n > 0) so mystery(1)
Third run:
n = 1;
n--; // n = 0
(n = 0) so return the n*2 . And the return will be 4
Why? Cause the recursive function does not change the value of n

Alogrithm recursion codingbat

Recursion-2 > groupSum6
http://codingbat.com/prob/p199368
I modified the solution from the first one example where the condition of using 6 is not present.
Below working solution:
public boolean groupSum6(int start, int[] nums, int target) {
// Base case: if there are no numbers left, then there is a
// solution only if target is 0.
if (start >= nums.length) return (target == 0);
// Key idea: nums[start] is chosen or it is not.
// Deal with nums[start], letting recursion
// deal with all the rest of the array.
// Recursive call trying the case that nums[start] is chosen --
// subtract it from target in the call.
if (nums[start] == 6)
return groupSum6(start + 1, nums, target - nums[start]);
if (groupSum6(start + 1, nums, target - nums[start]))
return true;
// Recursive call trying the case that nums[start] is not chosen.
if (groupSum6(start + 1, nums, target)) return true;
// If neither of the above worked, it's not possible.
return false;
}
HOWEVER it is not working when I'd replace
if (nums[start] == 6)
return groupSum6(start + 1, nums, target - nums[start]);
with :
if (nums[start] == 6)
groupSum6(start + 1, nums, target - nums[start]);
//NOTE: missing return statement.
Then algo fails for arrays where the target is possible to get but without using 6. eg groupSum6(0, [5, 6, 2], 7) expected value false but returns true. takes 5+2, skipps 6, but as in description every 6 must be used.
My question is: how does the 'return' statement changes the flow of recursion
Because java is pass by reference you aren't passing the actual object when you pass parameters to a method. You are passing a reference to the objects. So when you pass a reference to your objects, but take out the return call, the reference never gets resolved back to the variables, and you essentially throw away the results of your recursive call
Try this simple program to see what I mean:
public static int foo(int x) {
x++;
if(x < 10) {
foo(x);
}
return x;
}
If we call System.out.println(foo(1)); this will print out 2, since the first x++ gets resolved, but you essentially throw away the results from all your recursive calls.
However if we change
if(x < 10) {
foo(x);
}
To:
if(x < 10) {
return foo(x);
}
The result will be 10 because we return the results from the recursive calls

Understanding a program that finds the minimum value of an array with recursion

I need some help to understand the following program that finds the smallest number inside an array, I understand that in recursion you're supposed to divide the problem in a base case which ends the recursion, and into smaller steps that eventually grow down into the initial base case.
I understand that the base case is satisfied whenever the index reaches the final position in the array. How ever, I don't really understand how in the following program, the method would call itself back to continue advancing throughout the array.
Why does it continue checking the values of the full array instead of just stopping after checking the first value?
public static double min(double[] elements, int index) {
if (index == elements.length - 1) {
return elements[index];
}
double val = min(elements, index + 1);
if (elements[index] < val)
return elements[index];
else
return val;
}
if (elements[index] < val)
return elements[index];
You're asking why it doesn't return there the first time, right? Well, it does, but that's fine, because it's already made the recursive call - it does that in this line:
double val = min(elements, index + 1);
So it will reach that call, descend a level, and repeat over and over until it reaches the base case termination condition:
if (index == elements.length - 1) {
return elements[index];
}
Then as it goes back up the call stack, it will make the actual comparisons and find the least.
Make sense?
Using this piece of java code would make it much simpler to understand:
public static double min(double[] elements, int index) {
if (index == elements.length - 1) {
System.out.println(elements[index] + " returned from recursion");
return elements[index];
}
double val = min(elements, index + 1);
if (elements[index] < val) {
System.out.println(elements[index] + " is less than " + val);
System.out.println(elements[index] + " returned from recursion");
return elements[index];
}
else {
System.out.println(val + " is less than " + elements[index]);
System.out.println(val + " returned from recursion");
return val;
}
}
Call min(array_from_which_to_find_min, 0);

Ternary Operator in Java

I'm trying to learn Java using my knowledge I have gained from programming in C. In C, I loved the ternary operation. I'm trying to apply this in Java but I'm not sure if I'm doing it correctly. For the following recursive method that sums the from 1 to n, I have the following:
public static void main(String[] args){
int n = 6;
System.out.printf("sum of %d is %d ", n, new learn().sum(n));
}
public int sum(int num){
int result;
result = (num == 1) ? result = 1 : result = num + sum(num - 1);
}
which is giving me an error by stating that + is undefined. If someone could point out where my mistake is at, that would be much appreciated!
Your sum method currently has a return type of void. It therefore cannot return anything. In that case, you cannot be using the method invocation expression as a value, as you do in
num + sum(..)
// or in
System.out.printf("sum of %d is %d ", n, new learn().sum(n));
Change it to
public int sum(int num) {
return (num == 1) ? 1 : num + sum(num - 1);
}
to get the behavior you want.
Assigning result within the ternary expression when you are assigning to it outside of the ternary expression is completely pointless since you can't use the intermediary assignment.
That wouldn't be correct in C, either. The ternary operator evaluates to the selected expression, so don't assign inside it (just assign the result), and you clearly intend your method to return an int. Change the return type and return result (or eliminate the variable entirely and just return the value of the ternary expression).
Change:
result = (num == 1) ? result = 1 : result = num + sum(num - 1);
To:
result = (num == 1) ? 1 : num + sum(num - 1);
What is inside the operators ?: are the possible values of "result".

Categories

Resources