2 things that I am confused about tail recursion - recursion

I've several confusion about tail recursion as follows:
some of the recursion functions are void functions for example,
// Prints the given number of stars on the console.
// Assumes n >= 1.
void printStars(int n) {
if (n == 1) {
// n == 1, base case
cout << "*";
} else {
// n > 1, recursive case
cout << "*"; // print one star myself
printStars(n - 1); // recursion to do the rest
}
}
and another example:
// Prints the given integer's binary representation.
// Precondition: n >= 0
void printBinary(int n) {
if (n < 2) {
// base case; same as base 10
cout << n;
} else {
// recursive case; break number apart
printBinary(n / 2);
printBinary(n % 2);
}
}
As we know by definition tail recursion should return some value from tail call. But for void functions it does not return any value. By intinction I think they are tail recursion but I am not confident about it.
another question is that, if a recursion function has several logical end, should tail recursion come at all logical ends or just one of the logical ends? I saw someone argued that only one of the logical ends is OK, but I am not sure about that. Here's my example:
// Returns base ^ exp.
// Precondition: exp >= 0
int power(int base, int exp) {
if (exp < 0) {
throw "illegal negative exponent";
} else if (exp == 0) {
// base case; any number to 0th power is 1
return 1;
} else if (exp % 2 == 0) {
// recursive case 1: x^y = (x^2)^(y/2)
return power(base * base, exp / 2);
} else {
// recursive case 2: x^y = x * x^(y-1)
return base * power(base, exp - 1);
}
}
Here we have logical end as tail recursion and another one that is not tail recursion. Do you think this function is tail recursion or not? why?

Related

Need help recursion explanation Leetcode

How does this code work? (leetcode 95 question) I don't understand how the 2 recursions work inside the for loop. Does the 2nd inner for loop end when the recursive function returns NULL? Or would it continue executing the 3rd inner for loop?
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
if(n == 0) {
return {};
}
vector<TreeNode*> ans = generateT(1,n);
return ans;
}
vector<TreeNode*> generateT(int l, int r) {
if(l > r) return {nullptr};
vector<TreeNode*> ans;
for(int i=l; i <= r; ++i) {
for(TreeNode*left: generateT(l, i-1)) {
for(TreeNode* right:generateT(i+1, r)) {
ans.push_back(new TreeNode(i));
ans.back()->left = left;
ans.back()->right = right;
}
}
}
return ans;
}
};
Problem statement:
Given an integer n, return all the structurally unique BST's (binary search trees), which has exactly n nodes of unique values from 1 to n. Return the answer in any order.
Does the 2nd inner for loop end when the recursive function returns NULL?
No. The recursive function is not returing NULL, it is returning vector of nullptr.
Or would it continue executing the 3rd inner for loop?
Of course, it will.
How does this code work? I don't understand how the 2 recursions work inside the loop.
I suppose the following snippet is the cause of confusion, so commented the case when nullptr provided by outer loop.
vector<TreeNode*> generateT(int l, int r) {
if(l > r) return { nullptr };
vector<TreeNode*> ans;
for ( int i = l; i <= r; i++ ) {
// if l = 0, i = 0
for ( TreeNode* left :generateT(l, i-1) ) // if l = 0, i = -1, returns { nullptr } (vector of nullptr)
for (TreeNode* right :generateT(i+1, r)) { // now this snippet will execute
auto node = new TreeNode(i);
ans.push_back(node);
node->left = left; // the nullptr we have from the outer loop, will provide null value for this
node->right = right;
}
}
return ans;
}
Visually, for a combination of node where,
a
\
b
/ \
null c
/
null
the above pattern occurs the provided { nullptr } from outer loop will come in handy setting left node.

Counting the number

I have got a code that generates all possible correct strings of balanced brackets. So if the input is n = 4 there should be 4 brackets in the string and thus the answers the code will give are: {}{} and
{{}}.
Now, what I would like to do is print the number of possible strings. For example, for n = 4 the outcome would be 2.
Given my code, is this possible and how would I make that happen?
Just introduce a counter.
// Change prototype to return the counter
int findBalanced(int p,int n,int o,int c)
{
static char str[100];
// The counter
static int count = 0;
if (c == n) {
// Increment it on every printout
count ++;
printf("%s\n", str);
// Just return zero. This is not used anyway and will give
// Correct result for n=0
return 0;
} else {
if (o > c) {
str[p] = ')';
findBalanced(p + 1, n, o, c + 1);
}
if (o < n) {
str[p] = '(';
findBalanced(p + 1, n, o + 1, c);
}
}
// Return it
return count;
}
What you're looking for is the n-th Catalan number. You'll need to implement binomial coefficient to calculate it, but that's pretty much it.

Big O of recursive functions with multiple function calls?

I'm having trouble determining the worst case time complexity of this recursive function:
long f(int n) {
if(n <= 0) return 1;
else {
return f(n / 2) + f(n / 2) + f(n / 2);
}
}
I understand that if you were just returning f(n / 2) once, it would be O(log n). So I was wondering if having it three, four, five, etc times would affect the function's big O. Thanks!
Multiplying by a constant never affects the complexity. Of course, the execution time is roughly tripled, but the issue is how the time increases with respect to the value of n, not what the clock says.
Do note that this applies so easily because you're calling the same function with the same value; this could be reliably replaced by
return 3 * f(n/2)
If you had three different calls, such as
return f(n/2) + f(int(sqrt(n)) + f(n-1)
... then you'd have to compute the complexity of each and consider only the most complex. That isn't hard with this function; however, with a more complex function, such as the Collatz sequence, you'd have a more difficult time considering all of the 2nd- and 3rd-order complexities. You would also have more trouble with a call to an indirectly recursive function, such as
long f(int n);
long g(int n) {
if(n <= 2) return 1;
else {
return f(n*n mod 10) + g(n-2);
}
}
long f(int n) {
if(n <= 0) return 1;
else {
return f(n / 2) + g(n / 2);
}
}
Bottom line: your question is simple, but beware of follow-up questions.

how does second recursive that is return numberOfPaths(m-1, n) + numberOfPaths(m, n-1) call works?

How does second recursive that is return numberOfPaths(m-1, n) + numberOfPaths(m, n-1) call works??
#include <iostream>
using namespace std;
// Returns count of possible paths to reach cell at row number m and column
// number n from the topmost leftmost cell (cell at 1, 1)
int numberOfPaths(int m, int n)
{
// If either given row number is first or given column number is first
if (m == 1 || n == 1)
return 1;
// If diagonal movements are allowed then the last addition
// is required.
return numberOfPaths(m-1, n) + numberOfPaths(m, n-1);
// + numberOfPaths(m-1,n-1);
}
int main()
{
cout << numberOfPaths(3, 3);
return 0;
}
It calls the function numberOfPaths again. Once with m-1 and n and once with m and n-1 and adds their results.
If you called numberOfPaths(2,2) it would call numberOfPaths(1,2) and numberOfPaths(2,1) which both return 1 and thus numberOfPaths(2,2) would return 2.

How to calculate factorial of a factorial recursively?

I have encountered the following problem:
N is positive non-zero integer and I have to calculate the product of : N*(N-1)^2*(N-2)^3*..*1^N.
My solution so far is as follows:
N*myFact(N-1)*fact(N-1)
The thing is I'm not allowed to use any helping functions, such as 'fact()'.
EDIT: Mathematically it can be represented as follows: N!*(N-1)! (N-2)!..*1!
This function is called the superfactorial. A recursive implementation is
long superFact(n) {
if (n < 2) return 1;
long last = superFact(n-1);
long prev = superFact(n-2);
return last * last / prev * n;
}
but this is very inefficient -- it takes about 3*F(n) recursive calls to find superFact(n), where F(n) is the n-th Fibonacci number. (The work grows exponentially.)
Try:
int myFact(int n) {
return n == 1 ? 1 : myFact(n-1)*n;
}
I assume this needs to be accomplished with 1 function i.e. you're not allowed to create a fact helper function yourself.
You can use the fact that myFact(n-1) / myFact(n-2) == (n-1)!
int myFact(int n)
{
if (n == 0 || n == 1) {
return 1
} else {
// (n - 1)!
int previousFact = myFact(n - 1) / myFact(n - 2);
return myFact(n - 1) * previousFact * n;
}
}

Resources