1

Attempting to do a recursion exercise but I'm getting lost on how to create a method to get the sum of all elements in a list.

Here's what I have so far:

    public int countNumberOfElements(int [] elements){
int count = elements.length;
    if (elements.length == 0) {
        return 0;
    }
    else {
        return (countNumberOfElements(elements) + elements[count-1]);
    }
}
4
  • You need to pass position(index) and array in recursive method. And do like return elements[pos] + sumOfElements(pos+1, elements) means sum of current index value with sum of later indexed sub-array part Commented Aug 14, 2021 at 16:54
  • I posted a suggestion which did the wrong thing because that method is really badly named. It should be called something like sumElements or something similar, not *count*NumberOfElements Commented Aug 14, 2021 at 16:58
  • 1
    @FedericoklezCulloca oops I forgot to rename the method! I was doing another exercise and didn't change the name. Thanks for the reminder! Commented Aug 16, 2021 at 14:06
  • 1
    Note that the sum of ints can produce a result requiring long. Commented Aug 16, 2021 at 18:44

6 Answers 6

2

You need to add one parameters to your method: index, to keep track of your current position in the array:

public int sumOfElements(int[] elements, int index) {
    if (index >= elements.length)
        return 0;
    return elements[index] + sumOfElements(elements, index + 1);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Not sure why you got downvoted, this looks correct. Only minor quibble is that the test could just be index == elements.length - the assumption is that this would be called internally (so it shouldn't be public, but you're following the OP there) so index will be at most elements.length.
@RaffleBuffle Yeah, this code could use == aswell, but I personally prefer >= just incase someone parses an index higher than the element count.
0

you have to remove the last element

public static int countNumberOfElements(int[] elements) {
    int count = elements.length;
    if (elements.length == 0) {
        return 0;
    } else {
        int newArray[] = Arrays.copyOf(elements, count - 1);
        return (countNumberOfElements(newArray) + elements[count - 1]);
    }
}

Comments

0

Try something like this.

 int getSum(int[] items){
    return getSum(items, items.length - 1, 0);
 }

 int getSum(int[] items, int index, int sum){
    return index < 0 ? sum: getSum(items, index - 1, sum + items[index]);
 }

Comments

0

You could try:

static int findSum(int A[], int N){
    if (N <= 0)
        return 0;
    return (findSum(A, N - 1) + A[N - 1]);
}

where A is the array and N is the length of the array.

P.S. you mention a list in your question and then use and array in your example so I'm assuming you mean array 👍

Comments

0

You can create separate recursive method and call it from your method:

public int countNumberOfElements(int[] elements) {
    if (elements.length == 0)
        return 0;
    else
        return countNumberOfElementsRec(elements, 0);
}

public int countNumberOfElementsRec(int[] elements, int index) {
    if (index >= elements.length)
        return 0;
    else
        return elements[index] + countNumberOfElementsRec(elements, index + 1);
}

Comments

-1

Whittling the problem down element by element can result in stack overflow for even moderate sized arrays. This can be avoided by adding range values first and last to the recursive method's argument list and splitting the resulting range (roughly) in half to generate two sub-ranges which differ by no more than 1 in length. Recursively apply this splitting process on each sub-range until you get down to ranges containing a single element, whose "sum" is the value of that element. Then sum the results of the recursive calls and keep passing the cumulative results back up the recursion tree. The repeated halving reduces the number of recursive calls to O(log(elements.length)) rather than O(elements.length). The recurrence for the running time is T(n) = 2T(n/2) + O(1) => O(n), so this approach (like the solutions proposed by others) calculates the sum in linear time.

I have broken the implementation into a public front-end which takes the array as its sole argument, and a separate private recursion which has additional arguments for the range info. This hides the range bookkeeping from the end user. This is a common and useful trick when the recursion requires info which can be derived from the data itself, or involves value or type checking which only needs to be performed once up-front. Separating those derivations and checks into a front-end reduces the amount of work done in the recursive calls and makes the public facing method interface more user friendly. I've also made the return type long, because the sum of two ints can overflow the capacity of an int. The following code:

class Test {

    // Public facing front end
    public static long sumArray(int [] elements){
        int count = elements.length;
        if (count == 0) {
            return 0L;
        } else {
            return _sumArray_(elements, 0, count - 1);
        }
    }

    // Private recursive worker-bee to do the actual task.
    private static long _sumArray_(int [] elts, int first, int last) {
        // When focus is on a single element, return its value
        if (last == first) {
            return (long) elts[first];
        }
        // Otherwise find the mid-range index for the current range
        int mid = first + (last - first) / 2;
        // Sum the sums of the two resulting sub-ranges
        return _sumArray_(elts, first, mid) + _sumArray_(elts, mid + 1, last);
    }

    public static void main(String[] args) {
        int [] ary = {5,6,7,1,2,3,4,8,9,10};
        System.out.println(sumArray(ary));
    }
}

produces the correct answer of 55 for the test data provided in main.

To summarize, this solution:

  • yields correct answers, even if the array contains very large int values (returns long to avoid integer overflow);
    • Example: processing int [] ary = {2147483647,2147483647}; with methods which return int will yield -2 rather than the correct answer of 4294967294
  • doesn't require the end-user to remember and supply other arguments in addition to the data itself;
  • matches the time complexity of other proposed solutions; and
  • dominates all of the other solutions on the size of the recursive stack, so it won't cause stack overflows if you use it for arrays containing hundreds of thousands of elements or more.
    • Example: methods which divide a problem of size n into subproblems of size 1 and n-1 will generate a java.lang.StackOverflowError on large arrays such as int [] ary = new int[100000]; java.util.Arrays.fill(ary, 42);, while splitting the problem in successive halves handles an array with 100M elements with no problems.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.