Java Recursion 1
Java Recursion 1
Java
Recursion 1
Pre-requisites:
Basics of programming like loops, conditionals, functions, and data structures (like arrays, lists, etc.)
What is Recursion?
In simple words, Recursion is a method that calls itself. The concept of recursion involves breaking down a
problem into smaller subproblems and solving each subproblem by calling itself.
Properties of Recursion:
Performing the same operations multiple times with different inputs
Breaking the problem into smaller parts with every try
A base condition is needed to stop the recursion otherwise infinite loop will occur.
Advantages:
Recursive solutions can often be more concise and easier to read than their iterative counterparts
Reuse code effectively
Syntax:
return statement
Example:
return a+b;
Java + DSA
Function Calls Itself:
A function can call other functions, and by that logic, it can call itself as well.A function calling itself is known as
recursion in programming.
Syntax of a function calling itself or Recursion:
myRecursiveFunction(parameter) {
if (base case)
return base_case_value ;
else
return myRecursiveFunction(modified_parameter);
//Recursive call
Base case: In simple terms, it is the very basic and smallest unit of any task.
The condition where the function stops calling itself or the recursive calls are stopped from growing in memory.
The recursion stops when this case is met and the base case is required to avoid an infinite loop.
Recursive call: This is a function calling itself with a smaller input each time, which is similar to reducing a big
task into smaller bits. It progressively moves us towards the base case.
Although a Call stack is invisible to a programmer, it is important to understand how it works, as it forms the
core concept of recursion.
Call stack :
A call stack is a data structure in memory, used to manage the execution of function calls in a program. It keeps
track of the order in which functions are called and their respective local variables and parameters.
The call stack operates on a Last In, First Out (LIFO) basis, meaning that the last function called is the first one to
finish and be removed from the stack.
Each function call creates a new stack frame, which is a block of memory that stores information specific to
that function call, including the return address (the location in the program where execution should continue
after the function call completes).
In the case of recursive functions, each recursive call adds a new stack frame. The stack frames continue to
stack up until the base case is reached, at which point the functions start to complete, and the stack frames are
popped off.
Mary needs to go to school, but she needs to pack lunch before she leaves her house. She makes a to-do list
dividing her big task into four smaller tasks.
Java + DSA
Gathering the Ingredients
Prepare Food
Prepare Food: Once Mary has gathered the ingredients, she moves on to the next task. Similarly, in the call stack,
when a function is done, it's taken off the top of the stack.
Pack Lunch: After preparing the food, Mary can pack her lunch. In the call stack, when the last function or task is
done, the stack is empty, and the overall process (or program) is complete.
So, in simple terms, the call stack is like Mary's to-do list. Each task (or function) is added to the top of the stack,
and when a task is completed, it's taken off the top. This continues until all tasks are done, just like Mary going
through her to-do list to get ready for school.
Coding Questions:
Make a function that calculates the factorial of n using recursion.
Code:
if (n == 0 || n == 1) {
return 1;
} else {
Java + DSA
Input:
number=5
Output:
factorial(1)
2*factorial(1) 2*1
3*factorial(2) 3*2*1
4*factorial(3) 4*3*2*1
5 * factorial(4) 5*4*3*2*1
factorial(5) 120
Each stack frame is added as we recursively call the function reducing the current input by 1, and multiplying it
by the current input. This continues till the base case is reached ie. either 0 or 1, where 1 is returned and the top
of the stack frame is evaluated as 1 and popped off. The values are evaluated one-by-one from top to bottom
of the stack, and after evaluating each expression, the top of the stack is cleared and the final output is
returned.
The space complexity of the recursive factorial function is O(n) as well. Since the maximum depth of the call
stack is n (the number of recursive calls made).
Java + DSA
Print n to 1
Code:
if (n < 1) {
return;
printNTo1(n - 1);
Input:
n=12
Output:
12 11 10 9 8 7 6 5 4 3 2 1
Code Explanation:
The printNumbers method is a recursive function that takes an integer n as its parameter. It has two parts:
If n is less than or equal to 0, the function returns without doing anything, stops the recursion.
If n is greater than 0, it prints the current value of n and then makes a recursive call to printNumbers with the
argument n-1. This leads to a sequence of decreasing numbers until the base case is reached.
Java + DSA
Print 1 to n(extra parameter)
Code:
if (start > n) {
return; }
System.out.print(start+" ");
printNumbers(start + 1, n);
Input:
n=5
Output:
12345
Code Explanation:
A recursive call is made to printNumbers with the incremented start and the input n, continuing the sequence of
increasing numbers until the base case is met. If start is less than or equal to n, it prints the current value of
start. If start is greater than n, the function returns, stopping the recursion. This is the condition to break out of
the recursion.
Time and Space Complexity:
The time complexity is O(n), since each recursive call, the program prints one number, and there are n recursive
calls.The space complexity is O(n) due to the recursion stack.n each recursive call, a new stack frame is added
to the call stack, and the maximum depth of the call stack is n.
if (start > n) {
return;
Java + DSA
printNumbers(start + 1, n);
System.out.print(start+" ");
}
Input:
n=7
Output:
7654321
Code Explanation:
If start is greater than n, the function returns, stopping the recursion. This is the condition to break out of the
recursion.
It makes a recursive call to printNumbers with the incremented start and the same n, continuing the sequence
of increasing numbers.
After the recursive call, it prints the current value of start, reversing the order of numbers
Java + DSA
static int calculateSum(int start, int end, int sum) {
return sum;
// Recursive case: add the current start to the sum and call
the function with the next start
Input:
n=5
Output:
Sum is: 15
Code Explanation:
The base case checks if start is greater than end. If true, it returns the current sum.In the recursive case, it adds
the current value of start to the sum and makes a recursive call with the next value of start and the updated
sum.Once the base case is reached,the sum is returned.
Time and Space Complexity:
The time complexity of this recursive solution is O(n), where n is the input value. This is because the recursive
function makes n calls, each contributing O(1) work.The space complexity is O(n) due to the recursive call stack.
In the worst case, the stack depth will be n, as each recursive call consumes space on the call stack.
if (n == 1) {
return 1;
Java + DSA
// Recursive case: add n to the sum of the numbers from 1 to
n-1
Input:
n=10
Output:
Sum is: 55
Code Explanation:
The base case checks if n is 1. If true, it returns 1 as the sum of integers from 1 to 1 is 1.In the recursive case, it adds
the current value of n to the sum of the numbers from 1 to n-1 by making a recursive call with the value n-1.
Make a function which calculates ‘a’ raised to the power ‘b’ using recursion.
Code:
if (b == 0) {
return 1;
Java + DSA
Input:
Passing in 2 and 3 as values in power method
Output:
Exponential value is 8
Code Explanation:
The base case checks if b is 0. If true, it returns 1 as any number raised to the power 0 is 1.In the recursive case, it
calculates a^(b-1) by making a recursive call with the value b-1 and then multiplies it by a.
Time Complexity:
Determine the number of recursive calls: Identify how many times the function is recursively called in terms of
the input size.
Define the work done per call: Analyze the amount of work done in each recursive call in terms of constant time
or the input size.
Write the recurrence relation: Express the time complexity in a recurrence relation that describes the number of
times the function is called and the work done in each call.
Solve the recurrence relation: Solve the recurrence relation to obtain the overall time complexity of the
algorithm.
Space Complexity:
Determine the maximum depth of the call stack:Identify how many times the function will be called recursively
before reaching the base case. This gives you the maximum depth of the call stack.
Define the space used per call:Analyze the amount of space used in each call in terms of constant space or the
input size.
Write the recurrence relation for space:Express the space complexity in a recurrence relation that describes the
maximum depth of the call stack and the space used in each call.
Solve the recurrence relation for space:Solve the recurrence relation to obtain the overall space complexity
of the algorithm.
Java + DSA