Returning multiple values from a recursive function - java

I have this problem where I have to convert a decimal number to binary and then store the bits in a linked list where the head node is the most significant bit and the last node is the least significant bit. Solving the problem itself is actually easy as you only need to keep taking the modulo of 2 recursively and add the result in the list until the decimal number becomes 0.
Where I'm stuck is that I have to write the function such that it returns a pair of number, (whether an array or a list) of the most significant bit and the last significant bit.
i.e: Inputting 14 in the function would return (1, 0), since 14 is 1110 in binary.
I do have access to the MSB and LSB easily(getFirst(), getLast()).
The function can only take one argument which is the decimal number.
Currently I have this current code:
public static void encodeBin(int n) {
if(n == 0) return; //Base case
else {
if(n % 2 == 0)
theList.addFirst(0);
else
theList.addFirst(1);
encodeBin(n / 2);
}
// return?
}
The problem is I can't figure out how return the 2 values. Haveing a return value means I can't call encodeBin() by itself.
Moreover, where should I create the list? If I put something like List<Integer> = new LinkedList<Integer>() at the very beginning of the function, then each time the function calls itself, it creates a new list and adds the bits in THAT new list not the original right?(The list created from when the function is called the first time)
Anybody knows how to solve this?

You cannot return 2 values. You are going to have to return some object that contains the 2 values. either an array or some new object, depending on your homework requirments and where this function is going to be used.
For the linkedlist creation, what you need is a recursive helper method. Your public method will be used to initialize your objects, start the recursion, and return your result. This allows your actual recursive function to have more than 1 argument.
public static SOME_TYPE encodeBin(int n) {
LinkedList result = new LinkedList();
encodeBin_helper(result,n);
// return the MSB and LSB
}
public static void encodeBin_helper(LinkedList theList, int n) {
if(n == 0) return; //Base case
else {
if(n % 2 == 0)
theList.addFirst(0);
else
theList.addFirst(1);
encodeBin_helper(theList, n/2);
}
}

You can't return two values separately. You can, however, return an array containing the first bit and the last bit or create your own class to hold this data, and return an instance of that class.
And about the list, I see two options:
Make it a static class variable
Make it an argument of the function (although I see you said you couldn't do this).
The first method would look like this:
public class MyClass {
private static List<Integer> theList = new LinkedList<Integer>();
// `encodeBin` method as you have it
}
The second method would look like this:
public static void encodeBin(int n, List<Integer> theList) {
if(n == 0) return; //Base case
else {
if(n % 2 == 0)
theList.addFirst(0);
else
theList.addFirst(1);
encodeBin(n / 2, theList);
}
}
You could then do something along the lines of
List<Integer> theList = new LinkedList<Integer>();
encodeBin(14, theList);
and theList would hold the appropriate bits as desired.
As a note, you might want to consider making this a list of booleans instead of integers, with true representing 1 and false representing 0.

I suggest declaring two methods:
(1) public static int[] encodeBin(int n)
and
(2) private static void encodeBin(LinkedList, int n)
The public method merely creates an empty list and then calls the private version passing both the empty list and the orignal input n as the parameters
something like this:
public static int[] encodeBin(int n) {
LinkedList<Integer> aList = new LinkedList<Integer>();
encodeBin(aList , n);
int MSB = aList.getFirst();
int LSB = aList.getLast();
return new int[] {MSB, LSB};
}
private static void encodeBin(LinkedList<Integer> list, n) {
//your recursive version here
}

Related

Can you have collections without storing the values in Java?

I have a question about java collections such as Set or List. More generally objects that you can use in a for-each loop. Is there any requirement that the elements of them actually has to be stored somewhere in a data structure or can they be described only from some sort of requirement and calculated on the fly when you need them? It feels like this should be possible to be done, but I don't see any of the java standard collection classes doing anything like this. Am I breaking any sort of contract here?
The thing I'm thinking about using these for is mainly mathematics. Say for example I want to have a set representing all prime numbers under 1 000 000. It might not be a good idea to save these in memory but to instead have a method check if a particular number is in the collection or not.
I'm also not at all an expert at java streams, but I feel like these should be usable in java 8 streams since the objects have very minimal state (the objects in the collection doesn't even exist until you try to iterate over them or check if a particular object exists in the collection).
Is it possible to have Collections or Iterators with virtually infinitely many elements, for example "all numbers on form 6*k+1", "All primes above 10" or "All Vectors spanned by this basis"? One other thing I'm thinking about is combining two sets like the union of all primes below 1 000 000 and all integers on form 2^n-1 and list the mersenne primes below 1 000 000. I feel like it would be easier to reason about certain mathematical objects if it was done this way and the elements weren't created explicitly until they are actually needed. Maybe I'm wrong.
Here's two mockup classes I wrote to try to illustrate what I want to do. They don't act exactly as I would expect (see output) which make me think I am breaking some kind of contract here with the iterable interface or implementing it wrong. Feel free to point out what I'm doing wrong here if you see it or if this kind of code is even allowed under the collections framework.
import java.util.AbstractSet;
import java.util.Iterator;
public class PrimesBelow extends AbstractSet<Integer>{
int max;
int size;
public PrimesBelow(int max) {
this.max = max;
}
#Override
public Iterator<Integer> iterator() {
return new SetIterator<Integer>(this);
}
#Override
public int size() {
if(this.size == -1){
System.out.println("Calculating size");
size = calculateSize();
}else{
System.out.println("Accessing calculated size");
}
return size;
}
private int calculateSize() {
int c = 0;
for(Integer p: this)
c++;
return c;
}
public static void main(String[] args){
PrimesBelow primesBelow10 = new PrimesBelow(10);
for(int i: primesBelow10)
System.out.println(i);
System.out.println(primesBelow10);
}
}
.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class SetIterator<T> implements Iterator<Integer> {
int max;
int current;
public SetIterator(PrimesBelow pb) {
this.max= pb.max;
current = 1;
}
#Override
public boolean hasNext() {
if(current < max) return true;
else return false;
}
#Override
public Integer next() {
while(hasNext()){
current++;
if(isPrime(current)){
System.out.println("returning "+current);
return current;
}
}
throw new NoSuchElementException();
}
private boolean isPrime(int a) {
if(a<2) return false;
for(int i = 2; i < a; i++) if((a%i)==0) return false;
return true;
}
}
Main function gives the output
returning 2
2
returning 3
3
returning 5
5
returning 7
7
Exception in thread "main" java.util.NoSuchElementException
at SetIterator.next(SetIterator.java:27)
at SetIterator.next(SetIterator.java:1)
at PrimesBelow.main(PrimesBelow.java:38)
edit: spotted an error in the next() method. Corrected it and changed the output to the new one.
Well, as you see with your (now fixed) example, you can easily do it with Iterables/Iterators. Instead of having a backing collection, the example would've been nicer with just an Iterable that takes the max number you wish to calculate primes to. You just need to make sure that you handle the hasNext() method properly so you don't have to throw an exception unnecessarily from next().
Java 8 streams can be used easier to perform these kinds of things nowadays, but there's no reason you can't have a "virtual collection" that's just an Iterable. If you start implementing Collection it becomes harder, but even then it wouldn't be completely impossible, depending on the use cases: e.g. you could implement contains() that checks for primes, but you'd have to calculate it and it would be slow for large numbers.
A (somewhat convoluted) example of a semi-infinite set of odd numbers that is immutable and stores no values.
public class OddSet implements Set<Integer> {
public boolean contains(Integer o) {
return o % 2 == 1;
}
public int size() {
return Integer.MAX_VALUE;
}
public boolean add(Integer i) {
throw new OperationNotSupportedException();
}
public boolean equals(Object o) {
return o instanceof OddSet;
}
// etc. etc.
}
As DwB stated, this is not possible to do with Java's Collections API, as every element must be stored in memory. However, there is an alternative: this is precisely why Java's Stream API was implemented!
Streams allow you to iterate across an infinite amount of objects that are not stored in memory unless you explicitly collect them into a Collection.
From the documentation of IntStream#iterate:
Returns an infinite sequential ordered IntStream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.
The first element (position 0) in the IntStream will be the provided seed. For n > 0, the element at position n, will be the result of applying the function f to the element at position n - 1.
Here are some examples that you proposed in your question:
public class Test {
public static void main(String[] args) {
IntStream.iterate(1, k -> 6 * k + 1);
IntStream.iterate(10, i -> i + 1).filter(Test::isPrime);
IntStream.iterate(1, n -> 2 * n - 1).filter(i -> i < 1_000_000);
}
private boolean isPrime(int a) {
if (a < 2) {
return false;
}
for(int i = 2; i < a; i++) {
if ((a % i) == 0) {
return false;
}
return true;
}
}
}

Linked list doesn't contain values greater than a certain number

How can I create a method that would check whether or not a linked list contains any number larger than a parameter?
Let's say we have the linked list
[ 8 7 1 3 ]. This would return true and
[ 10 12 3 2] would return false.
Would this work?
public boolean f(int k) {
for (int=0; int<linkedList.size(); i++) {
if (linkedList.get(i)>k)
return false;
}
else
return true;
}
Also, I need to mention, this method would not change the list in any way and it should still work if the list contains null elements.
Thanks!
With Java 8
public boolean f(int k) {
return !linkedList.stream().anyMatch(i-> i> k );
}
clarification: I assume that you want to return false from the method in the case that even a single element is higher then the given k. Hence I use anyMatch since we only need to look for one element that is higher. There is no need to loop over the whole list.
No this will not work how you have it currently. You need to loop through the whole list before returning. The only time you should return prematurely is if you find a reason to return false in this context. So move your return true outside of your loop and then you'd be fine.
Also, try to give meaning to your method and class definitions. Saying obj.f(12) doesn't really say much, whereas obj.noElementGreaterThan(12) says a lot more.
for example:
public boolean noElementGreaterThan( int k ) {
for( int i = 0; i < linkedList.size(); i++ )
{
if( linkedList.get(i) > k )
return false;
}
return true;
}
The reason this works is because it will loop through the entire list of objects, comparing each to the value passed in (k). If the value is greater than k, then it will return false, meaning in this case that it does have an element greater than k.
using streams you could do like this:
public boolean f(int k) {
List<Integer> filtered = linkedList.stream().filter(i -> i > k).collect(Collectors.toList());
return !filtered.isEmpty();
}

Recursively determine if it is possible to find a target number

I will explain the title better for starters. My problem is very similar to the common: find all permutations of an integer array problem.
I am trying to find, given a list of integers and a target number, if it is possible to select any combination of the numbers from the list, so that their sum matches the target.
It must be done using functional programming practices, so that means all loops and mutations are out, clever recursion only. Full disclosure: this is a homework assignment, and the method header is set as is by the professor. This is what I've got:
public static Integer sum(final List<Integer> values) {
if(values.isEmpty() || values == null) {
return 0;
}
else {
return values.get(0) + sum(values.subList(1, values.size()));
}
}
public static boolean groupExists(final List<Integer> numbers, final int target) {
if(numbers == null || numbers.isEmpty()) {
return false;
}
if(numbers.contains(target)) {
return true;
}
if(sum(numbers) == target) {
return true;
}
else {
groupExists(numbers.subList(1, numbers.size()), target);
return false;
}
}
The sum method is tested and working, the groupExists method is the one I'm working on. I think it's pretty close, if given a list[1,2,3,4], it will return true for targets such as 3 and 10, but false for 6, which confuses me because 1,2,3 are right in order and add to 6. Clearly something is missing. Also, The main problem I am looking at is that it is not testing all possible combinations, for example, the first and last numbers are not being added together as a possibility.
UPDATE:
After working for a bit based on Simon's answer, this is what I'm looking at:
public static boolean groupExists(final List<Integer> numbers, final int target) {
if(numbers == null || numbers.isEmpty()) {
return false;
}
if(numbers.isEmpty()) {
return false;
}
if(numbers.contains(target)) {
return true;
}
if(sum(numbers.subList(1, numbers.size())) == (target - numbers.get(0))) {
return true; }
else {
return groupExists(numbers.subList(1, numbers.size()), target);
}
}
For convenience, declare
static Integer head(final List<Integer> is) {
return is == null || is.isEmpty()? null : is.get(0);
}
static List<Integer> tail(final List<Integer> is) {
return is.size() < 2? null : is.subList(1, is.size());
}
Then your function is this:
static boolean groupExists(final List<Integer> is, final int target) {
return target == 0 || target > 0 && head(is) != null &&
(groupExists(tail(is), target) || groupExists(tail(is), target-head(is)));
}
There are no surprises, really, regular checking of base cases plus the final line, where the left and right operands search for a "group" that does or does not, respectively, include the head.
The way I have written it makes it obvious at first sight that these are all pure functions, but, since this is Java and not an FP language, this way of writing it is quite suboptimal. It would be better to cache any function calls that occur more than once into final local vars. That would still be by the book, of course.
Suppose you have n numbers a[0], a[1], ..., a[n-1], and you want to find out if some subset sums to N.
Suppose you have such a subset. Now, either a[0] is included, or it isn't. If it's included, then there must exist a subset of a[1], ..., a[n] which sums to N - a[0]. If it isn't, then there exists a subset of a[1], ..., a[n] which sums to N.
This leads you to a recursive solution.
Checking all combinations is factorial (there's a bit missing on your implementation).
Why not try a different (dynamic) approach: see the Hitchhikers Guide to Programming Contests, page 1 (Subset Sum).
Your main method will be something like:
boolean canSum(numbers, target) {
return computeVector(numbers)[target]
}
computeVector return the vector with all numbers that can be summed with the set of numbers.
The method computeVector is a bit trickier to do recursively, but you can do something like:
boolean[] computeVector(numbers, vector) {
if numbers is empty:
return vector
addNumber(numbers[0], vector)
return computeVector(tail(numbers), vector);
}
addNumber will take vector and 'fill it' with the new 'doable' numbers (see hitchhikers for an explanation). addNumber can also be a bit tricky, and I'll leave it for you. Basically you need to write the following loop in recrusive way:
for(j=M; j>=a[i]; j--)
m[j] |= m[j-a[i]];
The lists of all possible combinations can be reached by asking a very simple decision at each recursion. Does this combination contain the head of my list? Either it does or it doesn't, so there are 2 paths at each stage. If either path leads to a solution then we want to return true.
boolean combination(targetList, sourceList, target)
{
if ( sourceList.isEmpty() ) {
return sum(targetList) == target;
} else {
head = sourceList.pop();
without = combination(targetList, sourceList, target); // without head
targetList.push(head);
with = combination(targetList, sourceList, target); // with head
return with || without;
}
}

Recursive isMember method with only two arguments!

I need to create a recursive Boolean method named isMemeber. The method should accept two arguments ONLY: an array and a value. The method should return true if the value is found in the array, or false if the value is not found in the array.
I think that the base case will be if the passed array is empty, but I need help with the recursive case:
public static boolean isMember(int[] array, int value)
{
if(array.length==0){
return false;
}else{
return isMember(???);
}
}
Here is how it looks with position variable:
public static boolean isMember(int[] array, int value, int position)
{
if (position > -1)
{
if (array[position] == value)
{
return true;
}
else
{
return isMember(array, value, position - 1);
}
}
return false;
}
If you need to use recursion you can copy the array on each recursion. This is inefficent, but using recursion is inefficient compared with using a loop. e.g. Arrays.indexOf()
public static boolean isMember(int[] array, int value) {
if(array.length == 0) return false;
if(array[0] == value) return true;
int[] array2 = new int[array.length-1];
System.arraycopy(array,1,array2,0,array2.length);
return isMember(array2, value);
}
There is a slight issue with your problem. If you are going to use recursion then each array element needs to have a subsey of elements otherwise whay do you passed to the recursive method? If this is not the casr and the case is as you stated then solving this problem with recursion isnot appropriate. Also you are missing the value comparison.
See the MSDN Array class. This looks like it is c#. Maybe try the Array.Find<T> method.
Update:
For Java, I'd recommend looking at Arrays (Java 2 Platform):
binarySearch
public static int binarySearch(int[]
a,
int key)
Searches the specified array of ints for the specified value using the binary search algorithm. The array must be sorted (as by the sort method above) prior to making this call. If
it is not sorted, the results are
undefined. If the array contains
multiple elements with the specified
value, there is no guarantee which one
will be found.
Parameters:
a - the array to be searched.
key - the value to be searched for.
Returns:
index of the search key, if it is contained in the list; otherwise,> (-(insertion point) - 1).
The insertion point is defined as the point at which the key would be inserted into the list: the index of the first element greater than the key, or list.size(), if all elements
in the list are less than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the key is found. See Also: sort(int[])
If this is homework and they want it recursive, then maybe you should:
1 look for the middle value of the array and check if it matches. If it matches, return true
2 apply the function to the first half of the array. If it returns true, return true
3 apply the function to the second half of the aray. If it returns true, return true
4 return false
No code since it is homework.
EDIT: Is the array ordered?
I was just doing the question, and checking answers for alternative ways. Maybe this might be useful when you have to match names to String arrays.
public class Recursion {
public static void main(String[] args) {
String[] array = {"Tom", "Mary"};
if(isMember(array,"John"))
System.out.print("Found!");
else
System.out.println("Not Found!");
}
public static boolean isMember(String[] array, String name)
{
int i = array.length;
if(array.length == 0)
return false;
if(array[i - 1].equals(name))
return true;
else
{
String[] array2 = new String[array.length - 1];
for(int b = 0; b< array.length -1; b++)
{
array2[b] = array[b];
}
return isMember(array2, name);
}
}
}

Refactor this recursive method?

I'm pretty new to the idea of recursion and this is actually my first attempt at writing a recursive method.
I tried to implement a recursive function Max that passes an array, along with a variable that holds the array's size in order to print the largest element.
It works, but it just doesn't feel right!
I have also noticed that I seem to use the static modifier much more than my classmates in general...
Can anybody please provide any general tips as well as feedback as to how I can improve my code?
public class RecursiveTry{
static int[] n = new int[] {1,2,4,3,3,32,100};
static int current = 0;
static int maxValue = 0;
static int SIZE = n.length;
public static void main(String[] args){
System.out.println(Max(n, SIZE));
}
public static int Max(int[] n, int SIZE) {
if(current <= SIZE - 1){
if (maxValue <= n[current]) {
maxValue = n[current];
current++;
Max(n, SIZE);
}
else {
current++;
Max(n, SIZE);
}
}
return maxValue;
}
}
Your use of static variables for holding state outside the function will be a source of difficulty.
An example of a recursive implementation of a max() function in pseudocode might be:
function Max(data, size) {
assert(size > 0)
if (size == 1) {
return data[0]
}
maxtail = Max(data[1..size], size-1)
if (data[0] > maxtail) {
return data[0]
} else {
return maxtail
}
}
The key here is the recursive call to Max(), where you pass everything except the first element, and one less than the size. The general idea is this function says "the maximum value in this data is either the first element, or the maximum of the values in the rest of the array, whichever is larger".
This implementation requires no static data outside the function definition.
One of the hallmarks of recursive implementations is a so-called "termination condition" which prevents the recursion from going on forever (or, until you get a stack overflow). In the above case, the test for size == 1 is the termination condition.
Making your function dependent on static variables is not a good idea. Here is possible implementation of recursive Max function:
int Max(int[] array, int currentPos, int maxValue) {
// Ouch!
if (currentPos < 0) {
raise some error
}
// We reached the end of the array, return latest maxValue
if (currentPos >= array.length) {
return maxValue;
}
// Is current value greater then latest maxValue ?
int currentValue = array[currentPos];
if (currentValue > maxValue) {
// currentValue is a new maxValue
return Max(array, currentPos + 1, currentValue);
} else {
// maxValue is still a max value
return Max(array, currentPos + 1, maxValue);
}
}
...
int[] array = new int[] {...};
int currentPos = 0;
int maxValue = array[currentPos] or minimum int value;
maxValue = Max(array, currentPos, maxValue);
A "max" function is the wrong type of thing to write a recursive function for -- and the fact you're using static values for "current" and "maxValue" makes your function not really a recursive function.
Why not do something a little more amenable to a recursive algorithm, like factorial?
"not-homework"?
Anyway. First things first. The
static int[] n = new int[] {1,2,4,3,3,32,100};
static int SIZE = n.length;
have nothing to do with the parameters of Max() with which they share their names. Move these over to main and lose the "static" specifiers. They are used only once, when calling the first instance of Max() from inside main(). Their scope shouldn't extend beyond main().
There is no reason for all invocations of Max() to share a single "current" index. "current" should be local to Max(). But then how would successive recurrences of Max() know what value of "current" to use? (Hint: Max() is already passing other Max()'s lower down the line some data. Add "current" to this data.)
The same thing goes for maxValue, though the situation here is a bit more complex. Not only do you need to pass a current "maxValue" down the line, but when the recursion finishes, you have to pass it back up all the way to the first Max() function, which will return it to main(). You may need to look at some other examples of recursion and spend some time with this one.
Finally, Max() itself is static. Once you've eliminated the need to refer to external data (the static variables) however; it doesn't really matter. It just means that you can call Max() without having to instantiate an object.
As others have observed, there is no need for recursion to implement a Max function, but it can be instructive to use a familiar algorithm to experiment with a new concept. So, here is the simplified code, with an explanation below:
public class RecursiveTry
{
public static void main(String[] args)
{
System.out.println(Max(new int[] {1,2,4,3,3,32,100}, 0, 0));
}
public static int Max(int[] n, int current, int maxValue)
{
if(current < n.Length)
{
if (maxValue <= n[current] || current == 0))
{
return Max(n, current+1, n[current]);
}
return Max(n, current+1, maxValue);
}
return maxValue;
}
}
all of the static state is gone as unnecessary; instead everything is passed on the stack. the internal logic of the Max function is streamlined, and we recurse in two different ways just for fun
Here's a Java version for you.
public class Recursion {
public static void main(String[] args) {
int[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
System.out.println("Max: " + max(0, data));
}
public static int max(int i, int[] arr) {
if(i == arr.length-1) {
return arr[i];
}
int memo = max(i+1, arr);
if(arr[i] > memo) {
return arr[i];
}
return memo;
}
}
The recurrence relation is that the maximum element of an array is either the first element, or the maximum of the rest of the array. The stop condition is reached when you reach the end of the array. Note the use of memoization to reduce the recursive calls (roughly) in half.
You are essentially writing an iterative version but using tail recursion for the looping. Also, by making so many variables static, you are essentially using global variables instead of objects. Here is an attempt at something closer to a typical recursive implementation. Of course, in real life if you were using a language like Java that doesn't optimize tail calls, you would implement a "Max" function using a loop.
public class RecursiveTry{
static int[] n;
public static void main(String[] args){
RecursiveTry t = new RecursiveTry(new int[] {1,2,4,3,3,32,100});
System.out.println(t.Max());
}
RecursiveTry(int[] arg) {
n = arg;
}
public int Max() {
return MaxHelper(0);
}
private int MaxHelper(int index) {
if(index == n.length-1) {
return n[index];
} else {
int maxrest = MaxHelper(index+1);
int current = n[index];
if(current > maxrest)
return current;
else
return maxrest;
}
}
}
In Scheme this can be written very concisely:
(define (max l)
(if (= (length l) 1)
(first l)
(local ([define maxRest (max (rest l))])
(if (> (first l) maxRest)
(first l)
maxRest))))
Granted, this uses linked lists and not arrays, which is why I didn't pass it a size element, but I feel this distills the problem to its essence. This is the pseudocode definition:
define max of a list as:
if the list has one element, return that element
otherwise, the max of the list will be the max between the first element and the max of the rest of the list
A nicer way of getting the max value of an array recursively would be to implement quicksort (which is a nice, recursive sorting algorithm), and then just return the first value.
Here is some Java code for quicksort.
Smallest codesize I could get:
public class RecursiveTry {
public static void main(String[] args) {
int[] x = new int[] {1,2,4,3,3,32,100};
System.out.println(Max(x, 0));
}
public static int Max(int[] arr, int currPos) {
if (arr.length == 0) return -1;
if (currPos == arr.length) return arr[0];
int len = Max (arr, currPos + 1);
if (len < arr[currPos]) return arr[currPos];
return len;
}
}
A few things:
1/ If the array is zero-size, it returns a max of -1 (you could have another marker value, say, -MAX_INT, or throw an exception). I've made the assumption for code clarity here to assume all values are zero or more. Otherwise I would have peppered the code with all sorts of unnecessary stuff (in regards to answering the question).
2/ Most recursions are 'cleaner' in my opinion if the terminating case is no-data rather than last-data, hence I return a value guaranteed to be less than or equal to the max when we've finished the array. Others may differ in their opinion but it wouldn't be the first or last time that they've been wrong :-).
3/ The recursive call just gets the max of the rest of the list and compares it to the current element, returning the maximum of the two.
4/ The 'ideal' solution would have been to pass a modified array on each recursive call so that you're only comparing the first element with the rest of the list, removing the need for currPos. But that would have been inefficient and would have bought down the wrath of SO.
5/ This may not necessarily be the best solution. It may be that by gray matter has been compromised from too much use of LISP with its CAR, CDR and those interminable parentheses.
First, let's take care of the static scope issue ... Your class is defining an object, but never actually instantiating one. Since main is statically scoped, the first thing to do is get an object, then execute it's methods like this:
public class RecursiveTry{
private int[] n = {1,2,4,3,3,32,100};
public static void main(String[] args){
RecursiveTry maxObject = new RecursiveTry();
System.out.println(maxObject.Max(maxObject.n, 0));
}
public int Max(int[] n, int start) {
if(start == n.length - 1) {
return n[start];
} else {
int maxRest = Max(n, start + 1);
if(n[start] > maxRest) {
return n[start];
}
return maxRest;
}
}
}
So now we have a RecursiveTry object named maxObject that does not require the static scope. I'm not sure that finding a maximum is effective using recursion as the number of iterations in the traditional looping method is roughly equivalent, but the amount of stack used is larger using recursion. But for this example, I'd pare it down a lot.
One of the advantages of recursion is that your state doesn't generally need to be persisted during the repeated tests like it does in iteration. Here, I've conceded to the use of a variable to hold the starting point, because it's less CPU intensive that passing a new int[] that contains all the items except for the first one.

Categories

Resources