0% found this document useful (0 votes)
45 views

Triangular Numbers: Finding The NTH Term Using A Loop

The document discusses triangular numbers, which are the sums of the natural numbers up to any given number. It describes two methods for calculating the nth triangular number: using a loop to sum the columns from n to 1, and using recursion by defining the nth term as the sum of n and the (n-1)th term. The key aspects of recursion are that a method calls itself and there must be a base case to prevent infinite recursion, here defined as returning 1 when n is 1. The document includes sample Java code that implements the recursive solution and output showing its step-by-step execution.

Uploaded by

Randy Tabaog
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views

Triangular Numbers: Finding The NTH Term Using A Loop

The document discusses triangular numbers, which are the sums of the natural numbers up to any given number. It describes two methods for calculating the nth triangular number: using a loop to sum the columns from n to 1, and using recursion by defining the nth term as the sum of n and the (n-1)th term. The key aspects of recursion are that a method calls itself and there must be a base case to prevent infinite recursion, here defined as returning 1 when n is 1. The document includes sample Java code that implements the recursive solution and output showing its step-by-step execution.

Uploaded by

Randy Tabaog
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 5

Data Structures and Algorithms in Java 1

Module 6: Recursion
Triangular Numbers
It's said that the Pythagorians, a band of mathematicians in ancient Greece who worked under Pythagoras (of Pythagorian
theorem fame), felt a mystical connection with the series of numbers 1, 3, 6, 10, 15, 21, … (where the … means the series
continues indefinitely). Can you find the next member of this series?
The nth term in the series is obtained by adding n to the previous term. Thus the second term is found by adding 2 to the
first term (which is 1), giving 3. The third term is 3 added to the second term (which is 3), giving 6, and so on. The numbers
in this series are called triangular numbers because they can be visualized as a triangular arrangements of objects, shown as
little squares in Figure 6.1.
Finding the nth Term Using a Loop
Suppose you wanted to find the value of some arbitrary nth term in the series; say the fourth term (whose value is 10). How
would you calculate it? Looking at Figure 6.2, you might decide that the value of any term can be obtained by adding up all
the vertical columns of squares.
In the fourth term, the first column has four little squares, the second column has three, and so on. Adding 4+3+2+1 gives
10.

Figure 6.1: The triangular numbers

Figure 6.2: Triangular number as columns


The following triangle() method uses this column-based technique to find a triangular number. It sums all the columns,
from a height of n to a height of 1.
int triangle(int n)
{
int total = 0;
while(n > 0) // until n is 1
{
total = total + n; // add n (column height) to total
--n; // decrement column height
}

return total;
}
The method cycles around the loop n times, adding n to total the first time, n-1 the second time, and so on down to 1,
quitting the loop when n becomes 0.

Module 6: Recursion
Data Structures and Algorithms in Java 2

Finding the nth Term Using Recursion


The loop approach may seem straightforward, but there's another way to look at this problem. The value of the nth term can
be thought of as the sum of only two things, instead of a whole series. These are
1. The first (tallest) column, which has the value n.
2. The sum of all the remaining columns.
This is shown in Figure 6.3.

Figure 6.3: Triangular number as column plus triangle


Finding the Remaining Columns
If we knew about a method that found the sum of all the remaining columns, then we could write our triangle() method,
which returns the value of the nth triangular number, like this:
int triangle(int n)
{
return( n + sumRemainingColumns(n) ); // (incomplete
version)
}
But what have we gained here? It looks like it's just as hard to write the sumRemainingColumns() method as to write the
triangle() method in the first place.

Notice in Figure 6.3, however, that the sum of all the remaining columns for term n is the same as the sum of all the
columns for term n-1. Thus, if we knew about a method that summed all the columns for term n, we could call it with an
argument of n-1 to find the sum of all the remaining columns for term n:
int triangle(int n)
{
return( n + sumAllColumns(n-1) ); // (incomplete version)
}
But when you think about it, the sumAllColumns() method is doing exactly the same thing the triangle() method is
doing: summing all the columns for some number n passed as an argument. So why not use the triangle() method itself,
instead of some other method? That would look like this:
int triangle(int n)
{
return( n + triangle(n-1) ); // (incomplete version)
}
It may seem amazing that a method can call itself, but why shouldn't it be able to? A method call is (among other things) a
transfer of control to the start of the method. This transfer of control can take place from within the method as well as from
outside.
Passing the Buck
All this may seem like passing the buck. Someone tells me to find the 9th triangular number. I know this is 9 plus the 8th
triangular number, so I call Harry and ask him to find the 8th triangular number. When I hear back from him, I'll add 9 to
whatever he tells me, and that will be the answer.
Harry knows the 8th triangular number is 8 plus the 7th triangular number, so he calls Sally and asks her to find the 7th
triangular number. This process continues with each person passing the buck to another one.
Where does this buck-passing end? Someone at some point must be able to figure out an answer that doesn't involve asking
another person to help them. If this didn't happen, there would be an infinite chain of people asking other people questions;
a sort of arithmetic Ponzi scheme that would never end. In the case of triangle(), this would mean the method calling
itself over and over in an infinite series that would paralyze the program.
The Buck Stops Here
To prevent an infinite regress, the person who is asked to find the first triangular number of the series, when n is 1, must
know, without asking anyone else, that the answer is 1. There are no smaller numbers to ask anyone about, there's nothing
left to add to anything else, so the buck stops there. We can express this by adding a condition to the triangle() method:
int triangle(int n)

Module 6: Recursion
Data Structures and Algorithms in Java 3

{
if(n==1)
return 1;
else
return( n + triangle(n-1) );
}
The condition that leads to a recursive method returning without making another recursive call is referred to as the base
case. It's critical that every recursive method have a base case to prevent infinite recursion and the consequent demise of the
program.
The triangle.java Program
Does recursion actually work? If you run the triangle.java program, you'll see that it does. Enter a value for the term
number, n, and the program will display the value of the corresponding triangular number. Listing 6.1 shows the
triangle.java program.

Listing 6.1 The triangle.java Program


// triangle.java
// evaluates triangular numbers

import java.io.*; // for I/O


////////////////////////////////////////////////////////////////
class TriangleApp
{
static int theNumber;

public static void main(String[] args) throws IOException


{
System.out.print("Enter a number: ");

System.out.flush();

theNumber = getInt();

int theAnswer = triangle(theNumber);

System.out.println("Triangle="+theAnswer);
} // end main()

//-------------------------------------------------------------

public static int triangle(int n)


{
if(n==1)
return 1;
else
return( n + triangle(n-1) );
}

//-------------------------------------------------------------

public static String getString() throws IOException


{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}

//-------------------------------------------------------------

public static int getInt() throws IOException


{
String s = getString();
return Integer.parseInt(s);
}

//-------------------------------------------------------------

} // end class TriangleApp

The main() routine prompts the user for a value for n, calls triangle(), and displays the return value. The triangle()
method calls itself repeatedly to do all the work.
Here's some sample output:
Enter a number: 1000
Triangle = 500500
What's Really Happening?

Module 6: Recursion
Data Structures and Algorithms in Java 4

Let's modify the triangle() method to provide an insight into what's happening when it executes. We'll insert some
output statements to keep track of the arguments and return values:
public static int triangle(int n)
{
System.out.println("Entering: n=" + n);

if(n==1)
{
System.out.println("Returning 1");
return 1;
}
else
{
int temp = n + triangle(n-1);
System.out.println("Returning " + temp);
return temp;
}
}
Here's the interaction when this method is substituted for the earlier triangle() method and the user enters 5:
Enter a number: 5

Entering: n=5
Entering: n=4
Entering: n=3
Entering: n=2
Entering: n=1
Returning 1
Returning 3
Returning 6
Returning 10
Returning 15

Triangle = 15

Each time the triangle() method calls itself, its argument, which starts at 5, is reduced by 1. The method plunges down
into itself again and again until its argument is reduced to 1. Then it returns. This triggers an entire series of returns. The
method rises back up, phoenixlike, out of the discarded versions of itself. Each time it returns, it adds the value of n it was
called with to the return value from the method it called.
The return values recapitulate the series of triangular numbers, until the answer is returned to main(). Figure 6.4 shows how
each invocation of the triangle() method can be imagined as being "inside" the previous one.
Notice that, just before the innermost version returns a 1, there are actually five different incarnations of triangle() in
existence at the same time. The outer one was passed the argument 5; the inner one was passed the argument 1.

Figure 6.4: The recursive triangle() method

Module 6: Recursion
Data Structures and Algorithms in Java 5

Characteristics of Recursive Methods


Although it's short, the triangle() method possesses the key features common to all recursive routines:
• It calls itself.
• When it calls itself, it does so to solve a smaller problem.
• There's some version of the problem that is simple enough that the routine can solve it, and return,
without calling itself.
In each successive call of a recursive method to itself, the argument becomes smaller (or perhaps a range described by
multiple arguments becomes smaller), reflecting the fact that the problem has become "smaller" or easier. When the
argument or range reaches a certain minimum size, a condition is triggered and the method returns without calling itself.
Is Recursion Efficient?
Calling a method involves certain overhead. Control must be transferred from the location of the call to the beginning of the
method. In addition, the arguments to the method, and the address to which the method should return, must be pushed onto
an internal stack so that the method can access the argument values and know where to return.
In the case of the triangle() method, it's probable that, as a result of this overhead, the while loop approach executes
more quickly than the recursive approach. The penalty may not be significant, but if there are a large number of method
calls as a result of a recursive method, it might be desirable to eliminate the recursion.
Another inefficiency is that memory is used to store all the intermediate arguments and return values on the system's
internal stack. This may cause problems if there is a large amount of data, leading to stack over flow.
Recursion is usually used because it simplifies a problem conceptually, not because it's inherently more efficient.

Module 6: Recursion

You might also like