Search code examples
javaalgorithmdivide-and-conquer

Average of a sequence of integers using divide and conquer


Given a sequence of integers, how can I find the average of it using a divide and conquer approach? I have to write a method "double avg(int[] a, int l, int r)" that finds the average in the array A, spanning from 'l' to 'r' as homework, but I get a StackOverflowError on the first recursive call - not in the second, though! - of my code, and I can't seem to understand why. Also, I'm pretty sure it doesn't give me a true average, but I found no way to check the average of a sequence using the divide and conquer. Here is my code:

public class Average {
public static void main(String[] args) {

    int[] A = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int l = 0;
    int r = A.length-1;
    System.out.println("Average of the array: "+averageCheck(A, l, r));

}

public static double averageCheck(int[] A, int l, int r) {
    if (l==r) {
        return A[l];
    }
    // Base Case: if there's just a single element it is the average of the array itself

    int mid = (l+r)/2;
    double avLeft = 0;
    double avRight = 0;

    avLeft = A[l]/r + averageCheck(A, l, mid);
    avRight = A[mid+1]/r + averageCheck(A, mid+2, r);

    double average = ( (avLeft*mid) + (avRight * (r-mid) ) ) /r;

    return average;

    }
}

Solution

  • Your recursivity does not end when r == l + 1. In this case, mid == l and in the second recursive call, mid+2 will be greater than r. Add this at the beginning of the function:

    if(l > r)
           return 0;
    

    Example, imagine l == 5 and r == 6, then mid will have the value 5. The second call will be averageCheck(A, 7, 6) as mid+2 is 7. In this call, the condition l == r will be false. Continue in the same logic and you will find that the recursivity will not end.

    I think also that it would be better if you calculate the sum recursively and divide by the length at the end.

    I suggest this solution:

    public class Average {
    public static void main(String[] args) {
    
        int[] A = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
        System.out.println("Average of the array: "+average(A));
    
    }
    
    public static double average (int[] A) {
           return averageCheck(A, 0, A.length - 1) / A.length;
    }
    
    public static double averageCheck(int[] A, int l, int r) {
    
    if (l > r)
        return 0;
    
    if (l==r) {
        return A[l];
    }
    // Base Case: if there's just a single element it is the average of the array itself
    
    int mid = (l+r)/2;
    double avLeft = 0;
    double avRight = 0;
    
    avLeft = averageCheck(A, l, mid);
    avRight = averageCheck(A, mid+1, r);
    
    double average = avLeft + avRight;
    
    return average;
    
    }
    }