Problems on Recursion
Problems on Recursion
Problems on Recursion
Problems on
Recursion
Today’s Checklist:
Q. Tower of Hanoi
The tower of Hanoi is a famous puzzle where we have three rods and N disks. The objective of the puzzle is to
move the entire stack to another rod. You are given the number of discs N. Initially, these discs are in rod 1. You
need to print all the steps of disc movement so that all the discs reach the 3rd rod. Also, you need to find the
total moves.
Note: The discs are arranged such that the top disc is numbered 1 and the bottom-most disc is numbered N.
Also, all the discs have different sizes and a bigger disc cannot be put on the top of a smaller disc..
Input: 2
Output: 3
Explanation: For N=2, steps will be as follows in the example and a total of 3 steps will be taken.
Input: 3
Output: 7
Explanation: For N=3 , steps will be as follows in the example and a total of 7 steps will be taken.
Java
C++ &+ DSA
DSA
Code:
if (N >= 1) {
cout << "move disk " << N << " from rod " << from <<
" to rod " << to << endl;
// Increment moves
moves++;
return moves;
Code Explanation:
The idea is to use the helper node to reach the destination using recursion. Below is the pattern for this problem:
Steps 1 and 3 are actually the same as the original problem. Thus we have derived a recursive solution for the
given problem.
//base case N=1 then simply move the disk from the source rod to the destination rod.
Create a function toh where pass the N (current number of disk), srcRod, destRod, helperRod
Now Making function call for N – 1 disk. (move them from src to helperRod
Then we are printing the current disk along with srcRod and destRo
Again making a fucntion call for N – 1 disk (move them from helperRod to srcROD).
Time complexity: O(2^N), As each function call calls itself two times by decreasing N just by 1.
Auxiliary Space: O(N), As at an instant we will have at most N function calls in the stack.
Code:
return;
Java
C++ &+ DSA
DSA
}
Code Explanation:
We are passing the array and current index as input and for each index
We print the curr element the call function for the next index and here the base will be when the index goes out
Space Complexity: O(n), Stack space grows linearly with array size due to recursion.
Output: 20
Code:
if (i == n - 1) {
return arr[i];
Code Explanation:
Increment i and call the recursive function for the new value of i
Compare the maximum value returned from the recursion function with arr[i]
Return the max between these two from the current recursion call.
C
Java &
++ + DSA
DSA
Time complexity: O(N), as for each index we are calling function only one (i.e for the next index), there will total
of n such calls 1 for each index
Auxiliary Space: O(N), since this will size the recursion stack, as function calls get piled up
Input : s = "banana"
c = 'a'
Code:
// Base Case
if (str.length() == 0) {
return "";
if (str[0] == ch) {
Code Explanation:
Here our recursive function’s base case will be when string length becomes 0.
And in the recursive function, if the encountered character is the character that we have to remove then call
the recursive function from the next character
else store this character in answer and then call the recursive function from the next character.
Time Complexity: O(n), as for each index we are making the function call once.
Q. Given an integer array nums of unique elements, return all possible subsets(the power set).(Leetcode 78)
Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
// Base Case
if (str.length() == 0) {
return "";
if (str[0] == ch) {
Code Explanation:
We are solving the problem using resSubsets() function, which takes the following inputs, i curr index of
elements in nums, the nums array of elements, prevSubset which has subset form up to this index, and then last
we have the res array which will store the final result
Base case: so in rec function call base case if if each completes the array i.e i==n then we’ll put push our
subset formed (i.e prevSubset) to the res
Now for each index, we have two choices either we include the curr char or we exclude it thus we form a new
extraSubset array in which we include the curr element of array
Now we make two function calls for the next element one including curr element (i.e with prevSubset) and
one excluding curr element (i.e with extra subset)
At last we return this res array which will have all the subset
Time Complexity: O(2^n), for each char in the string we make 2 calls
Input: aaa
Java
C++ &+ DSA
DSA
Code:
if (s.length() == 0) {
al.push_back(ans);
return;
findSubsequences(s.substr(1), ans);
Code Explanation:
In each recursive function call, we are making two calls when moving to the next one selecting the curr char
The base case when the string has nothing left we can thus add generated string to array and return
For other case make two calls first one while adding curr character to string and the other one without
adding it
Thus on running this function all the generated substrings will be pushed to global array of string i.e al
Time Complexity: O(2^n),for each char in string we make 2 calls
Input: k = 2, n = 3
Output: 1 2
1 3
2 3
Input: k = 5, n = 5
Output: 1 2 3 4 5
Code:
Java
C++ &+ DSA
DSA
void printSeqUtil(int n, int k, int len, int arr[]) {
if (len == k) {
printArr(arr, k);
return;
len++;
while (i <= n) {
arr[len - 1] = i;
i++;
len--;
int arr[k];
int len = 0;
int main() {
int k = 3, n = 7;
printSeq(n, k);
return 0;
Code Explanation:
The idea is to create an array of lengths k. The array stores the current sequence. For every position in the array,
we check the previous element and one by one put all elements greater than the previous element. If there is
no previous element (first position), we put all numbers from 1 to n.
Base Case: if len ==k If the length of the current increasing sequence becomes k, print i
Decide the starting number to put at the current position if len is 0 then it's 1 otherwise it is prev element +1,
as we are adding a new element increase the lengt
In the while loop Put all numbers (which are greater than the previous element) at the new position
Now undo the increase made to len to subtract 1 from it since len is shared among all functions all
Time Complexity: O(n*n!), as there are n! permutations and it requires O(n) time to print a permutation. T(n) =
n * T(n-1) + O(1) when reduced will result in O(n*n!) time.
Auxiliary Space: O(n), as at any time there will at most n function calls in the stack
Q. Finding all permutations of a string given all elements of the string are unique
Input: S = “ABC”
Java
C++ &+ DSA
DSA
Input: S = “XY”
if (l == r)
else {
swap(str[l], str[i]);
permute(str, l + 1, r);
Code Explanation:
Create a function permute() with parameters as input string, starting index of the string, ending index of the
strin
Call this function with values input string, 0, size of string –
In this function, if the value of L and R is the same then print the same strin
Else run a for loop from L to R and swap the current element in the for loop with the inputString[L
Then again call this same function by increasing the value of L by
After that again swap the previously swapped values to initiate backtracking
Time Complexity: O(N * N!) Note that there are N! permutations and it requires O(N) time to print a
permutation.
Auxiliary Space: O(N) As `l` progresses from 1 to `n-1`, the function generates up to `n` recursive calls until it
reaches the base condition `l == r`. So at any instant, there can be utmost N calls in the call stack.
Q. Given an array, generate all the possible subarrays of the given array using recursion.
Examples:
Input : [1, 2, 3]
Output : [1], [1, 2], [2], [1, 2, 3], [2, 3], [3]
Input : [1, 2]
Code:
if (end = = arr.size())
return;
Java
C++ &+ DSA
DSA
// Increment the end point and start from 0
else {
return;
Explanation: We use two pointers start and end to maintain the starting and ending point of the array and
follow the steps given below:
Increment the end index if start has become greater than end
Print the subarray from index start to end and increment the starting index
Q. Given a string, write a recursive function that checks if the given string is a palindrome, else, not a
palindrome.
Examples:
Input : malayalam
Output : Yes
malayalam.
Input : max
Output : No
Code:
int s, int e)
if (s = = e)
return true;
Java
C++ &+ DSA
DSA
// If first and last
if (str[s] ! = str[e])
return false;
// palindrome or not.
if (s < e + 1)
return true;
int n = strlen(str);
// considered as palindrome
if (n = = 0)
return true;
Explanation:
2) Else compare the first and last characters and recur for a remaining substring.
Q. Given two numbers a and b, the task is to find the GCD of the two numbers.
Input: a = 20, b = 28
Output: 4
Explanation: The factors of 20 are 1, 2, 4, 5, 10 and 20. The factors of 28 are 1, 2, 4, 7, 14 and 28. Among these
factors, 1, 2 and 4 are the common factors of both 20 and 28. The greatest among the common factors is 4.
Input: a = 60, b = 36
Output: 12
Java
C++ &+ DSA
DSA
Code:
Q. Given an integer, K. Generate all binary strings of size k without consecutive 1’s.
Examples:
Input : K = 3
Input : K = 4
Code:
if (n = = K) {
str[n] = '\0';
return;
if (str[n - 1] = = '1') {
str[n] = '0';
if (str[n - 1] = = '0') {
str[n] = '0';
str[n] = '1';
void generateAllStrings(int K) {
if (K <= 0)
return;
char str[K];
str[0] = '0';
Java
C++ &+ DSA
DSA
str[0] = '1';
Explanation: Idea behind that is IF string ends with ‘1’ then we put only ‘0’ at the end. IF string ends with ‘0’ then
we put both ‘0’ and ‘1’ at the end of string for generating new string.
Time complexity: 2^K where K is the size of the binary string. This is due to the fact that the algorithm
recursively generates all possible binary strings of length K.
Auxiliary space: O(K), since we are using a string array of size K to store the binary string.
Given an array of distinct integers candidates and a target integer target, return a list of all unique
combinations of candidates where the chosen numbers sum to target. You may return the combinations in any
order.
The same number may be chosen from candidates an unlimited number of times. Two combinations are
unique if the frequency of at least one of the chosen numbers is different.
The test cases are generated such that the number of unique combinations that sum up to target is less than
150 combinations for the given input.
Example 1:
Output: [[2,2,3],[7]]
Explanation:
2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
7 is a candidate, and 7 = 7.
Example 2:
Output: [[2,2,2,2],[2,3,3],[3,5]]
Example 3:
Output: []
Java
C++ &+ DSA
DSA
Code:
void recursive(vector < int > & candidates, int target, set <
vector < int >> & path, vector < int > & curr) {
if (target = = 0) {
sort(temp.begin(), temp.end());
if (path.count(temp) = = 0)
path.insert(temp);
return;
if (target < 0)
return;
curr.push_back(candidates[i]);
curr.pop_back();
vector < vector < int >> combinationSum(vector < int > &
candidates, int target) {
ans.push_back(a);
return ans;
Explanation: His code finds unique combinations of numbers from the candidates vector that sum up to the
target using a recursive backtracking approach. It stores unique combinations in a set to avoid duplicates.
Time complexity: Exponential, typically O(2^n) where 'n' is the number of candidates or the depth of recursion.
Space complexity: O(n * m), where 'n' is the number of combinations and 'm' is the average length of
combinations stored in the set.
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
Java
C++ &+ DSA
DSA
Example 1:
Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]
Example 2:
Input: n = 1
Output: ["()"]
Code:
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
return res;
v.push_back(str);
return;
};
Explanation: The idea is intuitive. Use two integers to count the remaining left parenthesis (n) and the right
parenthesis (m) to be added. At each function call add a left parenthesis if n >0 and add a right parenthesis if
m>0. Append the result and terminate recursive calls when both m and n are zero.
We build a table of n rows (1-indexed). We start by writing 0 in the 1st row. Now in every subsequent row, we look
at the previous row and replace each occurrence of 0 with 01, and each occurrence of 1 with 10.
For example, for n = 3, the 1st row is 0, the 2nd row is 01, and the 3rd row is 0110.
Given two integer n and k, return the kth (1-indexed) symbol in the nth row of a table of n rows.
Example 1:
Input: n = 1, k = 1
Output: 0
Explanation: row 1: 0
Java
C++ &+ DSA
DSA
Example 2:
Input: n = 2, k = 1
Output: 0
Explanation:
row 1: 0
row 2: 01
Example 3:
Input: n = 2, k = 2
Output: 1
Explanation:
row 1: 0
row 2: 01
Code:
if (N = = 1 && K = = 1)
return 0;
else
Explanation: This function determines the value (0 or 1) at position K in the sequence based on the kth
grammar sequence, where each subsequent row is derived from the previous row following a specific pattern.
Time complexity: O(log N) - The function divides the problem in half recursively by approximately half with
each step.
Space complexity: O(log N) - The space used on the call stack due to the recursive function calls, proportional
to the height of the recursion tree (log N).
The count-and-say sequence is a sequence of digit strings defined by the recursive formula:
countAndSay(1) = "1"
countAndSay(n) is the way you would "say" the digit string from countAndSay(n-1), which is then converted into
a different digit string.
To determine how you "say" a digit string, split it into the minimal number of substrings such that each substring
contains exactly one unique digit. Then for each substring, say the number of digits, then say the digit. Finally,
concatenate every said digit.
Java
C++ &+ DSA
DSA
For example, the saying and conversion for digit string "3322251":
Given a positive integer n, return the nth term of the count-and-say sequence.
Example 1:
Input: n = 1
Output: "1"
Example 2:
Input: n = 4
Output: "1211"
Explanation:
countAndSay(1) = "1"
Code:
if(n = = 1) return s;
j = i;
Explanation: This function creates a sequence by reading the previous sequence and saying out loud the
count of consecutive numbers.
Java
C++ &+ DSA
DSA
It starts with "1" as the initial value.
For each iteration, it reads the previous sequence, counts how many times a digit appears consecutively, and
says that count followed by the digit itself.
This process repeats for 'n' iterations to generate the desired sequence..
Time complexity: O(2^n) - The length of the string doubles with each iteration, performing operations linearly
proportional to the string length for each of the n iterations.
Space complexity: O(2^n) - Space on the call stack due to the recursive calls, proportional to the number of
iterations (n) and the length of the string generated at each step.
By listing and labeling all of the permutations in order, we get the following sequence for n = 3:
"123"
"132"
"213"
"231"
"312"
"321"
Example 1:
Input: n = 3, k = 3
Output: "213"
Example 2:
Input: n = 4, k = 9
Output: "2314"
Example 3:
Input: n = 3, k = 1
Output: "123"
Code:
class Solution {
public:
int fact = 1;
vector<int> numbers;
for(int i=1;i<n;i++){
// To find (n-1)!
Java
C++ &+ DSA
DSA
fact = fact*i;
numbers.push_back(i);
numbers.push_back(n);
string ans="";
k = k-1;
while(true){
numbers.erase(numbers.begin() + k/fact);
if(numbers.size()==0) break;
k = k%fact;
fact = fact/numbers.size();
return ans;
};
Explanation: Just keep fixing the position of element by finding their relevant group. Then remove that fixed
element from the data strucuture i.e. vector. Check for remaining elements until vector is empty.
Time complexity: O(n^2), Due to the erasing operation within the loop
Java
C++ &+ DSA
DSA
THANK
YOU !