Java recursive method difference - java

What is the difference between the following two methods:
public boolean recursionMethodOne(Node n) {
System.out.println(n.getValue());
return recursionMethodOne(n.next());
}
public void recursionMethodTwo(Node n) {
System.out.println(n.getValue());
recursionMethodTwo(n.next());
}
Which one do you use for recursion and what is the difference?
Thanks

Both your codes doesn't exits. You need to add a return for a test condition. For example:
public void recursionMethodTwo(Node n) {
if (n == null) {
// Standard way to exit a void function without executing remaing code
// note that return null; doesn't compile
return;
}
System.out.println(n.getValue());
recursionMethodTwo(n.next());
}
Returning a value or not depends on the kind of function.
For example if you need to calculate a factorial you need a result, if you need to print a list you don't.
So for your example seems that the method two is most closer to your needs.
Otherwise you need to ask yourself what is the returning boolean value of the function? If you have a nice answer to this question you can implement the code returning a value.

Related

Difference of two functions

I have one question regarding recursive functions and updating function parameters. Namely, I have two functions:
public static void populateArray(int[]level,Node root,int currentLevel) {
currentLevel++;
if(root.left!=null) {
populateArray(level,root.left,currentLevel);
}
level[currentLevel]++;
if(root.right!=null) {
populateArray(level,root.right,currentLevel);
}
}
public static void populateArray2(int[]level,Node root,int currentLevel) {
if(root.left!=null) {
currentLevel++;
populateArray2(level,root.left,currentLevel);
}
level[currentLevel]++;
if(root.right!=null) {
currentLevel++;
populateArray2(level,root.right,currentLevel);
}
}
These functions should fill an empty array with number of nodes in binary tree at each level. I thought that these functions work the same way, but it turns out that first function does that task correctly, and the second one doesn't, that is, currentLevel is not updated after returning from recursive call in the second function, and I am curious why is this the case?
I thought that in both functions, when we return from recursive call, parameter will be automatically updated (what is the case with the first function).
Second function will only work if after each recursive call we place currentLevel-- .. Does someone maybe know why this happens? Thank you in advance!
In the populateArray2 you're first accessing the level[currentLevel]++ and only then increase the currentLevel by 1 if the root.right != null.
I've added some comments to your code to highlight the difference:
public static void populateArray(int[]level,Node root,int currentLevel) {
currentLevel++; // Increase currentLevel by 1 first
if(root.left!=null) {
populateArray(level,root.left,currentLevel);
}
level[currentLevel]++; // Increase level by 1 after that
if(root.right!=null) {
populateArray(level,root.right,currentLevel);
}
}
public static void populateArray2(int[]level,Node root,int currentLevel) {
if(root.left!=null) {
currentLevel++;
populateArray2(level,root.left,currentLevel);
}
level[currentLevel]++; // Increase level by 1 first
if(root.right!=null) {
currentLevel++; // Increase currentLevel by 1 after that
populateArray2(level,root.right,currentLevel);
}
}
So that's the key difference here, causing different results because different levels are increased.
In addition, if both the root.left and root.right aren't null, you've done currentLevel++ twice in your populateArray2 method as well.
I'm not sure what you were trying to accomplish with populateArray2, but I would just remove it and stick with your original populateArray-method..
EDIT: As mentioned by #Simon, I've only addressed the difference between the two populateArray methods as was the question of OP. I haven't mentioned an actual fix for his requirements.
See #Simon's answer below for an actual fix following those requirements.
Your second function doesn't work properly because you are incrementing twice if the Node has both LEFT and RIGHT elements .
Hence u need currentElement-- at the end

How to Create a Public Boolean in Java?

This is my first time asking a question here, so I'll ask you to bear with me: I am trying to create a public boolean method, isEven(), that will check if a number is evenly divisible by two and return a value of true or false based on that. However, as this is a public method, I am unsure of how exactly to write it; this is my process thus far:
public boolean isEven()
{
if(WHAT_GOES_HERE? % 2 == 0)
return true;
else
return false;
}
I would appreciate some advice on how exactly to go about writing this method; thanks in advance!
The simplest way would be
public boolean isEven(int value){
return value % 2 == 0;
}
Using an if/else statement to return or set variables to boolean values is almost always redundant. Since you can return the condition you put in the if/else itself, the if/else is not needed.

Creating a JUnit for an array with a number less than 20 in the array, trying to create the assumed array, to then test

Assignment: Write a JUnit test assuming you have an array of int values and you only want the JUnit test to fail if any of the values are less than 20.
I know it only asks for the JUnit assuming the other methods are already created. But I want to create them anyway. However I do not know how to go about it. This is my code so far:
package ArrayJU;
public class ArrayJUTest {
public static void main(String[] args){
ArrayJUTest array = new ArrayJUTest();
int arr[] = {23,25,50,68,3};
System.out.println(array.arrayLessThan(arr));
}
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element>20){
return true;
}
else{
return false;
}
}
}
}
For the arrayLessThan Eclipse is telling me that I need to return a boolean, however I wouldn't know how to iterate through the array without a for loop. And if I return a true or a false outside the for loop it will defeat the purpose of what I'm trying to do with the if/else statements. How do I go about this? Your help will be greatly appreciated.
JUnit Test:
package ArrayJU;
import static org.junit.Assert.*;
import org.junit.Test;
public class JUnitArrayTest {
#Test
public void JUnitArTest(){
int[] arr = {32,52,89,12};
ArrayJUTest arra = new ArrayJUTest();
boolean poop = arra.arrayLessThan(arr);
assertEquals(false, poop);
}
}
Eclipse (really the java compiler) is complaining because after your for loop, your method doesn't return a boolean. The compiler doesn't figure out that the method never gets that far because it will always return during its very first iteration. Which is a problem anyway, since your method will never look beyond the first array element.
The typical way to code a loop like this is something along these lines:
public boolean arrayLessThan(int[] array) {
for (int element: array) {
if (element < 20) {
return false;
}
}
return true;
}
But beyond this, you're missing the point of JUnit. It's a framework, and you need to write your tests as methods of test classes that are written in a very specific manner required by that framework. You don't write your own main function - the framework provides one that looks through your code to find all your test classes and the tests implemented in each class, and then runs those tests for you.
You should google for documents / tutorials / examples of JUnit and then try again.
This question seems to be more about "why does this not compile and what the method return for an empty set" than "how do I write a JUnit test". I would recommend reading up on some JUnit tutorials (like this tutorial from mkyong) to get an understanding of them. I'll try to answer what I think is the first question.
The first thing is to note about the correctness of your loop based on your description. The loop will currently always return a value based on the first value of the array:
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element>20){
return true;
}
else{
return false;
}
}
}
Based on your description, it should only return false if any item matches your predicate (an item is less than 20). You are also getting a compiler error because it does not return anything for an empty array (0 elements). This would be one way to change it:
public boolean arrayLessThan(int array[]){
for (int element : array) {
if(element < 20){
return false;
}
}
return true;
}
And if I return a true or a false outside the for loop it will defeat
the purpose of what I'm trying to do with the if/else statements
Well, not really. It depends on how you want to model the 0-element array case. The best way to model it would be to return true because you cannot point to an element that does not satisfy your condition. This is known as vacuous truth.
You can read a good explanation for Java 8 streams with anyMatch and allMatch and vacuous truth in this question/answer.
I'm confused, there are two issues...
The first is that this isn't a junit test.
They look like this:
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
class HypotheticalClassTest {
private HypotheticalClass hypClass;
#Before
public void setup() {
hypClass = new HypotheticalClass();
}
#Test
public void ensureNoNumsLessThanTwenty() {
int[] result = hypClass.hypotheticalMethod();
// Some assertions. Check out the org.junit.Assert class.
}
}
Second, is you method arrayLessThan
Let's go through it step by step:
public boolean arrayLessThan(int array[]){
for (int element : array) { // For each int in array...
if(element>20){ // If element is greater than 20
return true; // Return true (returning stops the loop,
// do you want to stop on the
// first element greater than
// 20?)
} //
else{ // otherwise
return false; // Return false
}
} // Assuming there are no elements in the
// array (length 0) then this is where it
// comes. There's no return here, there
// needs to be, then it will stop
// complaining.
}
Looking at it now we see it doesn't compile because there is no return statement for the case of an empty array. Also we see it only checks the first element! Look up what continue does, it will fix the issue of only checking the first element, or write your condition differently.

Can a function end its caller's function?

Let's say we have the following two methods:
public static void repeat(){
while (1){
otherFunc();
}
}
public static void otherFunc(){
if (something){
//Here
}
}
Is there a way for, in the place of //Here, to cause a break or return in the repeat function?
Initially, I thought definitely not, because of the issue of scope. Also, if it was intended to be used like that, otherFunc could return a boolean and be placed in an if-statement to end the while-loop or the method.
However, I could not find anything to prove that it cannot have that behavior.
Is this possible?
Although I wrote this in Java, it would also be helpful to know if this stays true in C-languages also.
if can you change the code, do it like this:
public static void repeat()
{
while (otherFunc()) ;
}
public static boolean otherFunc()
{
if (something){
return true;
}
//more stuff...
return false;
}
In C you can use longjmp and setjmp functions but it is little bit tricky. More reading also on wikipedia http://en.wikipedia.org/wiki/Setjmp.h

Is there any way I can return a value from a loop and continue from where I left off?

Is there any way I can return a value from a loop and continuing from where I left off ?
In the following snippet, I want to return the current value of currVm. But I am unable to do so.
In the innermost loop of the snippet :
while(c <= currVm) {
allocatedVm(currVm);
c++;
}
a function named allocatedVm is called. I want to return the value of currVm and start again from where I left off. Is there any way out ?
#Override
public int getNextAvailableVm() {
Set<String> dataCenters = confMap.keySet();
for (String dataCenter : dataCenters) {
LinkedList<DepConfAttr> list = confMap.get(dataCenter);
Collections.sort(list, new MemoryComparator());
int size = list.size() - 1;
int count = 0;
while(size >= 0) {
DepConfAttr dca = (DepConfAttr)list.get(count);
int currVm = dca.getVmCount();
int c = 0;
while(c <= currVm) {
allocatedVm(currVm); // RETURN currVm
c++;
}
count++;
size--;
}
}
}
The best approach would probably be to write a method returning an Iterable<Integer>. That's not as easy in Java as it is in languages which support generator functions (e.g. C# and Python) but it's still feasible. If the code is short, you can get away with a pair of (nested) anonymous inner classes:
public Iterable<Integer> foo() {
return new Iterable<Integer>() {
#Override public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
// Implement hasNext, next and remove here
};
}
};
}
In your case I'd be tempted to break it into a separate non-anonymous class though, just for simplicity.
Anyway, the point of using Iterable is that an Iterator naturally has state - that's its purpose, basically. So it's a good fit for your requirements.
Another rather simpler approach would be to return all of the elements in one go, and make the caller perform the allocation on demand. Obviously that doesn't work well if there could be a huge number of elements, but it would be easier to understand.
not sure i understand what you need, but:
if you wish to notify the caller of the method that you've got a value during the running of the method, but don't wish to exit the method just yet, you can use listeners.
just create an interface as a parameter to your function, and have a function inside that will have the object as a parameter.
example:
interface IGotValueListener
{
public void onGotValue(MyClass obj);
}
public int getNextAvailableVm(IGotValueListener listener)
{
...
if(listener!=null)
listener.onGotValue(...);
}
now , for calling the method, you do:
int finalResult=getNextAvailableVm(new IGotValueListener ()
{
... //implement onGotValue
};
You can return from anywhere in your method , by just putting the return keyword. If you want to put a functionality to resume ur method from different places then u need to factor ur method in that way. You can use labels and if statements, set some static variables to mark the last execution place. If your application is not multi-threaded then u need not to worry with the use of static variable synchronization. Also if your method is too big and becoming hard to follow/read, then think about breaking it into smaller ones.

Categories

Resources