Is there a way to use recursion to populate arrays, without implementing method overloading? I want to build a method that takes only an int as argument, and returns an array. The only solution I have thought of is using method overloading; the function that takes int as argument builds the array and passes both the array and the int to the second function, which takes both the int and the array as arguments and implements the actual recursion.
Here is an example:
public static int[] recursiveBuilder(int depth, int[] anArray){
// Base case:
if (depth < 0){
return anArray;
}
// Recursion:
else{
anArray[depth] = depth;
depth--;
return recursiveBuilder(depth, anArray);
}
}
public static int[] recursiveBuilder(int depth){
return recursiveBuilder(depth, new int[depth + 1]);
}
If I declare the array in the recursive part of the overloading, the array would get initialized every time the recursion is called, so I used a second function to declare the array.
Is this approach considered good? Efficient? Is there a way to implement this dynamic in only one method?
Very commonly, a recursive solution requires two methods. The top method is called with the externally meaningful arguments, does any required set-up, and calls the recursive method. The recursive method takes additional arguments.
For example, a recursive binary search may have a top method that that takes as parameters only the probe and a reference to the array. The recursive method also takes a start and end index, so that it can limit itself to a slice of the array.
Java programs usually have a lot of small methods, and Java implementations are designed to handle that. If you can make your code be clear and work with two methods, go with two methods and move on to the next thing.
Related
I'm writing a recursive Java algorithm and I'm trying to make it work as fast as possible.
Now I'm facing a dilema since I would like to store some values into variables and would then like to pass the variable to the next recursive call (instead of passing the values directly). This approach would save be a few if statements. However, I'm wondering whether it would also make the program slower because it has to store a variable on every single call.
So I'm wondering whether this simplified problem:
public int Sum(int a) {
if (a==0)
return 0;
int tmp = heavyComputation(a);
return (tmp + Sum(a-1))
is any slower than this:
public int Sum(int a) {
if (a==0)
return 0;
return (heavyComputation(a) + Sum(a-1))
in this simplified example it doesn't really make much difference but in my code, the first approach would save me quite a few ugly if statements.
Thanks!
So for my research group I am attempting to convert some old C++ code to Java and am running into an issue where in the C++ code it does the following:
method(array+i, other parameters)
Now I know that Java does not support pointer arithmetic, so I got around this by copying the subarray from array+i to the end of array into a new array, but this causes the code to run horribly slow (I.e. 100x slower than the C++ version). Is there a way to get around this? I saw someone mention a built-in method on here, but is that any faster?
Not only does your code become slower, it also changes the semantic of what is happening: when you make a call in C++, no array copying is done, so any change the method may apply to the array is happening in the original, not in the throw-away copy.
To achieve the same effect in Java change the signature of your function as follows:
void method(array, offset, other parameters)
Now the caller has to pass the position in the array that the method should consider the "virtual zero" of the array. In other words, instead of writing something like
for (int i = 0 ; i != N ; i++)
...
you would have to write
for (int i = offset ; i != offset+N ; i++)
...
This would preserve the C++ semantic of passing an array to a member function.
The C++ function probably relied on processing from the beginning of the array. In Java it should be configured to run from an offset into the array so the array doesn't need to be copied. Copying the array, even with System.arraycopy, would take a significant amount of time.
It could be defined as a Java method with something like this:
void method(<somearraytype> array, int offset, other parameters)
Then the method would start at the offset into the array, and it would be called something like this:
method(array, i, other parameters);
If you wish to pass a sub-array to a method, an alternative to copying the sub-array into a new array would be to pass the entire array with an additional offset parameter that indicates the first relevant index of the array. This would require changes in the implementation of method, but if performance is an issue, that's probably the most efficient way.
The right way to handle this is to refactor the method, to take signature
method(int[] array, int i, other parameters)
so that you pass the whole array (by reference), and then tell the method where to start its processing from. Then you don't need to do any copying.
According to my understanding, a method with variable length argument and another method with array as an argument are interchangeable. for eg.
void test(int ... ints){} //method-1
is same as
void test (int [] ints){} //method-2
and we can't use both in the same class (Compile Time Error).
When I use method-1, I can call this method by passing some integers or by passing an array of integers since calling this method using some integers will implicitly create an array of those integers.
For eg.
test(1,2,3); //ok
test(new int[5]); //ok
But,
When I use method-2, I can't call this method by passing some integers as arguments.
test(new int[5]); //ok
test(1,2,3); //NOT OK
Questions:
1) If java implicitly creates an array of the arguments, why it is not able to call test(1,2,3) in case of method-2.
2) Why java doesn't allow using method-1 and method-2 together when both show different behavior?
One difference I could think of is you can have additional arguments to a metod after an int[] but you cant have a variable argument like that. Variable argument should always be the last parameter to a method. Example
void test(int[] a, int a) {} // works fine.
void test(int ... ints, int a){} // compile error.
1) If java implicitly creates an array of the arguments, why it is not
able to call test(1,2,3) in case of method-2.
Because 1,2,3 in test(1,2,3) is not an array, these are three different integers...You have to pass an Array of int to invoke method-2.
2) Why java doesn't allow using method-1 and method-2 together when
both show different behavior?
It creates ambiguity when you call method with array as an argument because array as an argument is allowed in case of varargs as well as array as an argument.
for example, if both method were allowed, test(new int[5]) will create an ambiguity.
The internal representation in the Java compiler of the function declarations in these two cases is identical. That's why the compiler wont let you declare two such functions with the same name.
The difference in the bahivour of these two declarations can be seen when you actually call the functions with the actual arguments. Since Java is a strongly typed language (with strict type checking) it doesn't allow you to pass three integers to the test (int[] a) method.
However, when you call test(int ... a) with test(1,2,3) the compiler generates intermediate code to make a temporary array of three integers and passes it onto the function.
I'm trying to make a recursive method that receives an array and traverse it like with a loop, but without a loop.
Couldn't find a way to make an index, and increase each time I call the method.
If you have a function f(array,index) make it do something with array[index] and return function(array,index+1). Finally, to start it off call function(array,0). If there are any variables or state you are building up over the course of the recursive function, also pass it via the arguments.
A shot in the dark, but
public void printMyArray (String[] test, int index) {
// verify the index isn't too large
// Grab a value and do something with it.
}
Edit: As stated above, you basically just need to run through each value in the array. The easiest is really carrying over an index value (in my opinion).
My slides say that:
A recursive call should always be on a smaller data structure than the current one
There must be a non recursive option if the data structure is too small
You need a wrapper method to make the recursive method accessible
Just reading this from the slides makes no sense, especially seeing as it was a topic from before christmas!
Could anyone try and clear up what it means please?
Thank you
A recurssive call should always be on a smaller data structure than the current one
In general this isn't true but if you are talking about linked lists manipulation with recursion it is. What it is implying is that you need to always be working towards a solution and this usually is dealing with a smaller problem than you started with.
Take for example Quicksort. Each time the function is called it is working with a smaller set of data.
Taking another example of printing a linked list, the next time you call the recursive function the argument should be the tail of the linked list (This code has an error in it, but that leads us to our next point)
void printList(List l){
print(l.head);
printList(l.tail);
}
There must be a non recurssive option if the data structure is too small
This means there should be a base case. The point where the function stops calling itself again.
int factorial(int n){
if ( n == 1 ){ //the base case is when n = 1
return 1;
}
return n*factorial(n-1);
}
Going back to the example of printing a linked list, there has to be a case where you only have an empty list left (in which case the function should do nothing). Going back to the code to print a linked list
void printList(List l){
if ( l.empty == true ){ //the base case is when the list l is empty
return;
}
print(l.head);
printList(l.tail);
}
You need a wrapper method to make the recurssive method accessible
I don't know Java, and it isn't really a language designed for recursion, however in many cases your recursive function will have more parameters than the person using the API should be able to see. You might for example want to have a counter in there.
You can have a wrapper function that simplifies the parameters to just what is needed. The wrapper function then calls the real worker function.
An example might be if we have a linked list class that has the recursive function to print the list. Its declaration would look something like this:
void printList(List l);
However as it is a class method, to someone using the API it doesn't make much sence to have to do this:
myList.printList(myList);
So a wrapper function could be created that doesn't have any paramters which then calls the code that does the work.
void printList(){
doPrintList(this); //pass in the List object as the first argument
}
Then all the programmer using the API has to do is:
myList.printList();