简体   繁体   中英

Finding the largest element in an array using recursion in Java

This is what I have so far, but I'm confused on how to keep track of the index. I would change the parameters of the method, but I'm not allowed. I can only use a loop to make another array. Those are the restrictions.

public class RecursiveFinder {

    static int checkedIndex = 0;
    static int largest = 0;


    public static int largestElement(int[] start){
        int length = start.length;

        if(start[length-1] > largest){
            largest = start[length-1];
            int[] newArray = Arrays.copyOf(start, length-1);
            largestElement(newArray);
        }
        else{
            return largest;
        }
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        int[] array1 = {0,3,3643,25,252,25232,3534,25,25235,2523,2426548,765836,7475,35,547,636,367,364,355,2,5,5,5,535};
        System.out.println(largestElement(array1));
        int[] array2 = {1,2,3,4,5,6,7,8,9};
        System.out.println(largestElement(array2));
    }

}

Recursive method doesn't need to keep the largest value inside.

2 parameters method

Start to call with:

largestElement(array, array.length-1)

Here is the method:

public static int largestElement(int[] start, int index) {
    if (index>0) {
        return Math.max(start[index], largestElement(start, index-1))
    } else {
        return start[0];
    }
}

The 3rd line of method is the hardest one to understand. It returns one of two elements, larges of the one of current index and of remaining elements to be checked recursively.

The condition if (index>0) is similar to while-loop. The function is called as long as the index remains positive (reaches elements in the array).


1 parameter method

This one is a bit tricky, because you have to pass the smaller array than in the previous iteration.

public static int largestElement(int[] start) {
    if (start.length == 1) {
        return start[0];
    }
    int max = largestElement(Arrays.copyOfRange(start, 1, start.length));
    return start[0] > max ? start[0] : max;
}

I hope you do this for the study purposes, actually noone has a need do this in Java.

You don't need to keep a largest variable outside your method - that's generally not a good practice with recursion which should return all context of the results.

When you think about recursion try to think in terms of a simple base case where the answer is obvious and then, for all other cases how to break it down into a simpler case.

So in pseduo-code your algorithm should be something like:

func largest(int[] array)
    if array has 1 element
        return that element
    else
        return the larger of the first element and the result of calling largest(remaining elements)

You could use Math.max for the 'larger' calculation.

It's unfortunate that you can't change the arguments as it would be easier if you could pass the index to start at or use lists and sublists. But your copying method should work fine (assuming efficiency isn't a concern).

An alternative to the algorithm above is to make an empty array the base case. This has the advantage of coping with empty arrays (by return Integer.MIN_VALUE):

int largest(int[] array) {
    return array.length == 0 
        ? Integer.MIN_VALUE
        : Math.max(array[0], largest(Arrays.copyOfRange(array, 1, array.length)));
}

Try that for the upper class, leave the main method it's is correct.

public class dammm {



public static int largestElement(int[] start){
int largest = start[0];

for(int i = 0; i<start.length; i++) {
    if(start[i] > largest){

        largest = start[i];
    }

    }return largest;
}

For this problem you really need to think about working with the base case. Take a look at some of the simple cases you would have to deal with:

  1. If the array is length 1, then you return the only value
  2. If the array is length 2, then you return the maximum of the two values
  3. If the array is length 3, then ?

From the above we can get an idea of the structure of the problem:

if array.length == 1 then
    return array[0]
else
    return the maximum of the values

In the above if we have only one element, it is the maximum value in the list. If we have two values, then we have to find the maximum of those values. From this, we can then use the idea that if we have three values, we can find the maximum of two of them, then compare the maximum with the third value. Expanding this into pseudo code, we can get something like:

if array.length == 1 then
    return array[0]
else
    new array = array without the first element (e.g. {1, 2, 3} => {2, 3})
    return maximum(array[0], largestElement(new array))

To explain the above a little better, think of execution like a chain (example for {1, 2, 3}).

  • Array: {1, 2, 3}, maximum(array[0] = 1, largestElement(new array = {2, 3}))
    • Array: {2, 3}, maximum(array[0] = 2, largestElement(new array = {3}))
      • Array: {3}, array[0] = 3 => length is 1 so return 3

The above then rolls back up the 'tree' structure where we get:

maximum (1, maximum(2, (return 3)))

Once you have the maximum value, you can use the sample principle as above to find the index with a separate method:

indexOf(array, maximum)
    if array[0] == maximum then
       return 0
    else if array.length == 1 then
       return -1 
    else
       new array = array without the first element (e.g. {1, 2, 3} => {2, 3})
       result = indexOf(new array, maximum)
       return (result == -1) ? result : result + 1

For looking into this more, I would read this from the Racket language. In essence it shows the idea of array made purely from pairs and how you can use recursion to do iteration on it.

If you are interested, Racket is a pretty good resource for understanding recursion. You can check out University of Waterloo tutorial on Racket. It can give you a brief introduction to recursion in an easy to understand way, as well as walking you through some examples to understand it better.

If your goal is to achieve this by using recursion, this is the code that you need. It is not the most efficient and it is not the best way to deal with the problem but it is probably what you need.

public static int largestElement(int[] start){
    int length = start.length;

    if (start.lenght == 1){
        return start[0];
    } else {
        int x = largestElement(Arrays.copyOf(start, length-1))
        if (x > start[length-1]){
            return x;
        } else {
            return start[length-1];
        }
    }       
}

Imagine that you have a set of numbers you just have to compare one number with the rest of them.

For example, given the set {1,8,5} we just have to check if 5 is larger than the largest of {1,8} . In the same way you have to check if 8 is larger than the largest of {1} . In the next iteration, when the set one have one value, you know that that value is the bigger of the set.

So, you go back to the previous level and check if the returned value ( 1 ) is larger than 8 . The result ( 8 ) is returned to the previous level and is checked against 5 . The conclusion is that 8 is the larger value

One parameter, no copying. Tricky thing is, we need to pass a smaller array to the same method. So a global variable is required.

    // Number of elements checked so far.
    private static int current = -1;

    // returns the largest element.
    // current should be -1 when user calls this method.
    public static int largestElement(int[] array) {
        if (array.length > 0) {
            boolean resetCurrent = false;

            if (current == -1) {
                // Initialization
                current = 0;
                resetCurrent = true;
            } else if (current >= array.length - 1) {
                // Base case
                return array[array.length - 1];
            }

            try {
                int i = current++;
                return Math.max(array[i], largestElement(array));
            } finally {
                if (resetCurrent) {
                    current = -1;
                }
            }
        }
        throw new IllegalArgumentException("Input array is empty.");
    }

If you can create another method, everything would be much simpler.

private static int recursiveFindLargest(int [] array, int i) {
    if (i > 0) {
        return Math.max(array[i], recursiveFindLargest(array, i-1));
    } else {
        return array[0];
    }
}

public static int largestElement(int [] array) {
    // For empty array, we cannot return a value to indicate this situation,
    //all integer values are possible for non-empty arrays.
    if (array.length == 0) throw new IllegalArgumentException();

    return recursiveFindLargest(array, array.length - 1);
}

You can modify the array using recursion by comparing two numbers in the array ( [n] and [n+1] ) and putting the bigger into the smaller's place. Therefore, by incrementing n, you compare all of the elements. Hence, last element of the array is the biggest.

public static int findLargest( int[] nums, int n ) {

  if ( nums[n] > nums[n+1] ) {
     nums[ n + 1 ] = nums[n];
  }

  else if ( n == nums.length - 2 ) { //if last element is bigger than previous one
     return nums[nums.length - 1]; 
  } 

  if( n == nums.length - 2 ){ return nums[n]; }
  return findLargest( nums, n + 1 );

}

Here is working example of code with one method param

    public int max(int[] list) {
        if (list.length == 2) return Math.max(list[0], list[1]);
        int max = max(Arrays.copyOfRange(list, 1, list.length));
        return list[0] < max ? max : list[0];
    }
private static int maxNumber(int[] arr,int n,int max){
    if(n<0){
        return max;
    }
   max = Math.max(arr[n],max);
   return maxNumber(arr,n-1,max);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM