vrnvav97
vrnvav97

Reputation: 53

How to fix the execution of this recursion code?

In this basic array problem, I need to add the sum or the value of the previous index of the array to the current index value using recursion.

For example, {5,3,1,2} becomes {5,8,9,11}.

Since the 0th index is the first index so it remains as it is.

I think my code is correct but instruction pointer is not flowing according to my dry run and the return statement (for the base condition) is not executing. Since I have my code in Java, after adding try-catch I'm getting output as expected. But adding try-catch is not the solution.

class kr1
{
    public static void main(String[] args) {
        int a[]= {5,1,3,9,5};
        a=addr (a,0,a.length);
        for (int i:a)
            System.out.print (i +" ");
    }

    static int[] addr(int a[],int i,int n)
    {
        if (i==0)
            addr(a,i+1,n);
        if (i==n-1)
        {
            a[i] = a[i]+a[i-1];
            return a ; //this return statement is not executing
        }
             //this below part is executing even if i has reached to n-1
        a[i] = a[i] + a[i-1];
        addr(a,i+1,n);
        return a;
    }
   }

Upvotes: 0

Views: 161

Answers (4)

ggorlen
ggorlen

Reputation: 56993

The problem is the first conditional,

if (i==0)
    addr(a,i+1,n);

Here, addr is called recursively, but after the call returns, execution continues on down to the end of the function and the line a[i] = a[i] + a[i-1]; throws an AIOOBE at a[-1]. The fix is:

if (i==0)
    return addr(a,i+1,n);

which prevents the rest of the function from executing.

Having said that, I'd like to suggest the following simplification:

class Main {
    public static void main(String[] args) {
        var res = addr(new int[] {5, 1, 3, 9, 5}, 1);
        System.out.println(java.util.Arrays.toString(res));
    }

    static int[] addr(int a[], int i) {
        if (i < a.length) {
            a[i] += a[i-1];
            return addr(a, i + 1);
        }

        return a;
    }
}

Since this is an in-place algorithm, I suggest making it void:

class Main {
    public static void main(String[] args) {
        var a = new int[] {5, 1, 3, 9, 5};
        addr(a, 1);
        System.out.println(java.util.Arrays.toString(a));
    }

    static void addr(int a[], int i) {
        if (i < a.length) {
            a[i] += a[i-1];
            addr(a, i + 1);
        }
    }
}

Writing a wrapper that handles the easy-to-mess-up 1 index for the initial call is wise.

Taking a step back, the problem is actually a poor fit for recursion in languages that don't provide tail call optimization because the call stack grows linearly in proportion to the input. That means you'll overflow the stack for medium-sized arrays of a few thousand elements. The best approach is to use a loop.

Upvotes: 0

Zhi Yuan
Zhi Yuan

Reputation: 194

static int[] addr(int a[],int i,int n)
{
    if (i==0)
        addr(a,i+1,n); // buggy
    if (i==n-1)
    {
        a[i] = a[i]+a[i-1];
        return a;
    }

    // code executed after if (i==0) block returns
    a[i] = a[i] + a[i-1];
    addr(a,i+1,n);
    return a;
}

As there is no return a; inside the if (i==0) block, the subsequent code block will be executed. Since the value of i is 0, a[i-1] is equivalent to a[-1], which results in an ArrayOutOfBoundsException being thrown.

You can resolve this by:

  1. Adding a return a; inside the if (i==0) block.

  2. Having the main function to call this recursive function with i = 1. That way, you can remove the if (i==0) block.


Since Java arrays are pass-by-reference, you actually don't need to return the array.

class kr1
{
    public static void main(String[] args) {
        int a[]= {5,1,3,9,5};
        addr (a,0,a.length);
        for (int i:a)
            System.out.print (i +" ");
    }

    static void addr(int a[],int i,int n)
    {
        if (i==0)
            addr(a,i+1,n);
            return;
        if (i==n-1)
        {
            a[i] = a[i]+a[i-1];
            return;
        }
        a[i] = a[i] + a[i-1];
        addr(a,i+1,n);
    }
   }

That would make the code more readable.

Upvotes: 2

Pythoscorpion
Pythoscorpion

Reputation: 166

just change this part of your code

if (i==0)
    addr(a,i+1,n);

to this one

if (i==0){
     addr(a,i+1,n);
     return a;
}

Upvotes: 0

oziomajnr
oziomajnr

Reputation: 1741

static int[] addr(int a[],int i,int n)
{
    if (i==0)
        return addr(a,i+1,n);
    if (i==n-1)
    {
        a[i] = a[i]+a[i-1];
        return a ; //this return statement is not executing
    }
    //this below part is executing even if i has reached to n-1
    a[i] = a[i] + a[i-1];
   return addr(a,i+1,n);
}

In recursion when recalling the function, you should return the value of the function call, you didn't do that. So I just added a return to the recalling functions and it worked. Also, check your algorithm, it fails when the length if the array is one, you could add a simple check to ensure that when the array size is 1 or zero the array is returned back and no manipulation is done to the array. Cheers.

Upvotes: 0

Related Questions