1. Recursion and 1D Arrays Example -- Find First Index We revisited an earlier method on Strings/1D arrays. The goal is to find the first index where an item occurs in the array. We worked on a slightly more general problem: find the first index of the value from a given starting point in the array
Write a method which finds the first index where a value occurs in an array starting at a given index, indexFrom: int findFirstIndex( double[] numbers, double value, int indexFrom )
As always we need to identify the "easy" and "hard" cases by considering the various situations for the given inputs. Here mainly indexFrom is of interest: 1. indexFrom is invalid: * report value not found 2. indexFrom is valid and contains the value: * report that index, no need to look further 3. indexFrom is valid but does not contain the value: * search for the value starting from the neighbor of indexFrom Translated in Java this becomes:

int findFirstIndex( double[] numbers, double value, int indexFrom )
{
    if ( index < 0 || indexFrom >= numbers.length )    // Case 1. Is starting point invalid?
    {
        return -1;   // value cannot be found starting from invalid index             
    }
    else if ( numbers[ indexFrom ] == value )          // Case 2. Is the value at given index?
    {
        return indexFrom;   // value found: report the index, no need to look further
    }
    else  // Case 3. Given index is valid, but does not have the value
    {
        // report the result from starting the search one cell to the right
        return findFirstIndex( numbers, value, indexFrom + 1 );
    }
}

    // a common mistake is to write the "else" part without the "return"
    else
    {
        // incorrect: missing return
        findFirstIndex( numbers, value, indexFrom + 1 );
    }
As a small variation we could consider a version where negative indices are not considered invalid. In this case we decided that we will pretend that the user meant starting at index 0.

int findFirstIndex( double[] numbers, double value, int indexFrom )
{
    if ( indexFrom >= numbers.length )  // Case 1a. Is starting point invalid?
    {
        return -1;   // value cannot be found starting from invalid index             
    }
    else if ( indexFrom < 0 )           // Case 1b. Normally invalid, but assume meant to start at 0
    {
        // correct user mistake and see what can be found starting at beginning, i.e. at 0
        return findFirstIndex( numbers, value, 0 );
    }
    else if ( numbers[ indexFrom ] == value )  // Case 2. Is value at given index?
    {
        return indexFrom;  // value found: report index, no need to look further
    }
    else  // Case 3. given index valid, but did not have the value
    {
        // report the result from starting the search one cell to the right
        return findFirstIndex( numbers, value, indexFrom + 1 );
    }
}
Example -- Find Last Index For Strings/1D Arrays we also implemented a version of the method that searched for the last index. This version is a bit harder, especially if we are not allowed to move backwards. Here is the recursive version. The main difference is that we cannot return immediately if the given index contains the value since the value may exist somewhere further down to the right. So instead, we should first see what can be found by searching further down to the right. 1. if anything is found to the right, this is the expected result since it occurs later 2. if nothing is found to the right, it might be at the given index so that is the second best option 3. if not found to the right and not found at the given index, it does not exist anywhere

int findLastIndex( double[] numbers, double value, int indexFrom )
{
    if ( index < 0 || indexFrom >= numbers.length )    // Case 1. Is starting point invalid?
    {
        return -1;  // value cannot be found starting from invalid index             
    }
    else
    {
        // see if the value exists somewhere further to the right of given index
        int laterIndex = findLastIndex( numbers, value, indexFrom+1 );

        if ( laterIndex != -1 )  // Was value found later (somewhere to the right)
        {
            return laterIndex;   // if found later, this is the preferred result
        }
        else if ( numbers[ indexFrom ] == value )  // Not found later, but maybe we have it?
        {
            return indexFrom;  // not found later, but we have it, so the best we can report
        }
        else
        {
            return -1;  // not found later and we do not have it: must not exist
        }
    }
}
Example -- Reverse Array The standard strategy to reverse an array can be described as follows:
0. keep two indices i, j that indicated the range that needs to be reveresed _____________________________ ________|_|_|_|_|_|_|________ i j 1. swap the values at indices i, j 2. do it again with updated i,j (i moves one step right, j moves one step left) Here do it again really means "continue reversing" so it could be expressed as: * (non-recursive) run the loop again with the new values of i,j * (recursive) reverse the range with the new values of i,j
We also need to think of the "easy case(s)" or about when to stop working:
* for loop-based solutions the question is typically phrased in this way: as long as __some-condition-true__: keep working
* for recursive solutions the question is typically phrased in this way: if __some-condition-true__: stop working
* so the two conditions tend to be the opposite of each other. In this example, the question is resolved as follows:
* (non-recursive) "as long as i in front of j, keep working" * (recursive) "if i not in front of j, stop working" [ not in front means "equal or after" so >= ]
Here is the code:

void reverse( double[] numbers, int i, int j )
{
    if ( i >= j )   // i no longer in front of j
    {
        return;     // nothing to do
    }
    else
    {
        // swap the two ends of the range
        double temp = numbers[ i ];
        numbers[ i ] = numbers[ j ];
        numbers[ j ] = temp;

        // "do it again", i.e. reverse the updated range
        reverse( numbers, i+1, j-1 );
    }
}
For this example we can write a shorter version whose condition is actually the same as the condition in loop version:

void reverse( double[] numbers, int i, int j )
{
    if ( i < j )  // if i in front of j, need to work
    {
        // swap the two ends of the range
        double temp = numbers[ i ];
        numbers[ i ] = numbers[ j ];
        numbers[ j ] = temp;

        // "do it again", i.e. reverse the updated range
        reverse( numbers, i+1, j-1 );
    }
}